Initial release
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
// 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
|
||||
|
||||
namespace VSTGUI {
|
||||
namespace Detail {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
struct Locale
|
||||
{
|
||||
Locale ()
|
||||
{
|
||||
origLocal = std::locale ();
|
||||
std::locale::global (std::locale::classic ());
|
||||
}
|
||||
|
||||
~Locale () noexcept
|
||||
{
|
||||
std::locale::global (origLocal);
|
||||
}
|
||||
|
||||
std::locale origLocal;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // Detail
|
||||
} // VSTGUI
|
||||
@@ -0,0 +1,50 @@
|
||||
// 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 "../../lib/ccolor.h"
|
||||
#include <string>
|
||||
|
||||
namespace VSTGUI {
|
||||
namespace Detail {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
inline bool parseColor (const std::string& colorString, CColor& color)
|
||||
{
|
||||
if (colorString.length () == 7)
|
||||
{
|
||||
if (colorString[0] == '#')
|
||||
{
|
||||
std::string rv (colorString.substr (1, 2));
|
||||
std::string gv (colorString.substr (3, 2));
|
||||
std::string bv (colorString.substr (5, 2));
|
||||
color.red = (uint8_t)strtol (rv.c_str (), nullptr, 16);
|
||||
color.green = (uint8_t)strtol (gv.c_str (), nullptr, 16);
|
||||
color.blue = (uint8_t)strtol (bv.c_str (), nullptr, 16);
|
||||
color.alpha = 255;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (colorString.length () == 9)
|
||||
{
|
||||
if (colorString[0] == '#')
|
||||
{
|
||||
std::string rv (colorString.substr (1, 2));
|
||||
std::string gv (colorString.substr (3, 2));
|
||||
std::string bv (colorString.substr (5, 2));
|
||||
std::string av (colorString.substr (7, 2));
|
||||
color.red = (uint8_t)strtol (rv.c_str (), nullptr, 16);
|
||||
color.green = (uint8_t)strtol (gv.c_str (), nullptr, 16);
|
||||
color.blue = (uint8_t)strtol (bv.c_str (), nullptr, 16);
|
||||
color.alpha = (uint8_t)strtol (av.c_str (), nullptr, 16);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
} // Detail
|
||||
} // VSTGUI
|
||||
@@ -0,0 +1,82 @@
|
||||
// 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
|
||||
|
||||
namespace VSTGUI {
|
||||
namespace Detail {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <bool nameHasExtension, size_t numIndicators>
|
||||
inline std::pair<size_t, size_t> rangeOfScaleFactor (const std::string& name,
|
||||
const char (&identicator)[numIndicators])
|
||||
{
|
||||
auto result = std::make_pair (std::string::npos, std::string::npos);
|
||||
size_t xIndex;
|
||||
if (nameHasExtension)
|
||||
{
|
||||
xIndex = name.rfind ("x.");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (name[name.size () - 1] != 'x')
|
||||
return result;
|
||||
xIndex = name.size () - 1;
|
||||
}
|
||||
if (xIndex == std::string::npos)
|
||||
return result;
|
||||
|
||||
for (auto i = 0u; i < numIndicators; ++i)
|
||||
{
|
||||
size_t indicatorIndex = name.find_last_of (identicator[i]);
|
||||
if (indicatorIndex == std::string::npos)
|
||||
continue;
|
||||
if (xIndex < indicatorIndex)
|
||||
continue;
|
||||
result.first = xIndex;
|
||||
result.second = indicatorIndex;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t numIndicators>
|
||||
inline bool decodeScaleFactorFromName (const std::string& name,
|
||||
const char (&identicator)[numIndicators],
|
||||
double& scaleFactor)
|
||||
{
|
||||
auto range = rangeOfScaleFactor<true> (name, identicator);
|
||||
if (range.first == std::string::npos)
|
||||
return false;
|
||||
std::string tmp (name);
|
||||
tmp.erase (0, ++range.second);
|
||||
tmp.erase (range.first - range.second);
|
||||
scaleFactor = UTF8StringView (tmp.c_str ()).toDouble ();
|
||||
return scaleFactor != 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static constexpr const char scaleFactorIndicatorChars[] = "#_";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
inline bool decodeScaleFactorFromName (const std::string& name, double& scaleFactor)
|
||||
{
|
||||
if (!decodeScaleFactorFromName (name, scaleFactorIndicatorChars, scaleFactor))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
inline std::string removeScaleFactorFromName (const std::string& name)
|
||||
{
|
||||
auto range = rangeOfScaleFactor<false> (name, scaleFactorIndicatorChars);
|
||||
if (range.first == std::string::npos)
|
||||
return "";
|
||||
auto result = name.substr (0, range.second);
|
||||
return result;
|
||||
}
|
||||
|
||||
} // Detail
|
||||
} // VSTGUI
|
||||
@@ -0,0 +1,160 @@
|
||||
// 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 "../uiattributes.h"
|
||||
#include "uidesclist.h"
|
||||
#include "uinode.h"
|
||||
|
||||
namespace VSTGUI {
|
||||
namespace Detail {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
UIDescList::UIDescList (bool ownsObjects) : ownsObjects (ownsObjects)
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
UIDescList::UIDescList (const UIDescList& uiDesc) : ownsObjects (false)
|
||||
{
|
||||
for (auto& child : uiDesc)
|
||||
add (child);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
UIDescList::~UIDescList () noexcept
|
||||
{
|
||||
removeAll ();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void UIDescList::add (UINode* obj)
|
||||
{
|
||||
if (!ownsObjects)
|
||||
obj->remember ();
|
||||
UIDescListContainerType::emplace_back (obj);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void UIDescList::remove (UINode* obj)
|
||||
{
|
||||
UIDescListContainerType::iterator pos =
|
||||
std::find (UIDescListContainerType::begin (), UIDescListContainerType::end (), obj);
|
||||
if (pos != UIDescListContainerType::end ())
|
||||
{
|
||||
UIDescListContainerType::erase (pos);
|
||||
obj->forget ();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void UIDescList::removeAll ()
|
||||
{
|
||||
for (const_reverse_iterator it = rbegin (), end = rend (); it != end; ++it)
|
||||
(*it)->forget ();
|
||||
clear ();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
UINode* UIDescList::findChildNode (UTF8StringView nodeName) const
|
||||
{
|
||||
for (const auto& node : *this)
|
||||
{
|
||||
auto& name = node->getName ();
|
||||
if (nodeName == UTF8StringView (name))
|
||||
return node;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
UINode* UIDescList::findChildNodeWithAttributeValue (const std::string& attributeName,
|
||||
const std::string& attributeValue) const
|
||||
{
|
||||
for (const auto& node : *this)
|
||||
{
|
||||
const std::string* attributeValuePtr =
|
||||
node->getAttributes ()->getAttributeValue (attributeName);
|
||||
if (attributeValuePtr && *attributeValuePtr == attributeValue)
|
||||
return node;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void UIDescList::sort ()
|
||||
{
|
||||
std::sort (begin (), end (), [] (const UINode* n1, const UINode* n2) {
|
||||
const std::string* str1 = n1->getAttributes ()->getAttributeValue ("name");
|
||||
const std::string* str2 = n2->getAttributes ()->getAttributeValue ("name");
|
||||
if (str1 && str2)
|
||||
return *str1 < *str2;
|
||||
else if (str1)
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
UIDescListWithFastFindAttributeNameChild::UIDescListWithFastFindAttributeNameChild ()
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void UIDescListWithFastFindAttributeNameChild::add (UINode* obj)
|
||||
{
|
||||
UIDescList::add (obj);
|
||||
const std::string* nameAttributeValue = obj->getAttributes ()->getAttributeValue ("name");
|
||||
if (nameAttributeValue)
|
||||
childMap.emplace (*nameAttributeValue, obj);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void UIDescListWithFastFindAttributeNameChild::remove (UINode* obj)
|
||||
{
|
||||
const std::string* nameAttributeValue = obj->getAttributes ()->getAttributeValue ("name");
|
||||
if (nameAttributeValue)
|
||||
{
|
||||
ChildMap::iterator it = childMap.find (*nameAttributeValue);
|
||||
if (it != childMap.end ())
|
||||
childMap.erase (it);
|
||||
}
|
||||
UIDescList::remove (obj);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void UIDescListWithFastFindAttributeNameChild::removeAll ()
|
||||
{
|
||||
childMap.clear ();
|
||||
UIDescList::removeAll ();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
UINode* UIDescListWithFastFindAttributeNameChild::findChildNodeWithAttributeValue (
|
||||
const std::string& attributeName, const std::string& attributeValue) const
|
||||
{
|
||||
if (attributeName != "name")
|
||||
return UIDescList::findChildNodeWithAttributeValue (attributeName, attributeValue);
|
||||
ChildMap::const_iterator it = childMap.find (attributeValue);
|
||||
if (it != childMap.end ())
|
||||
return it->second;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void UIDescListWithFastFindAttributeNameChild::nodeAttributeChanged (
|
||||
UINode* node, const std::string& attributeName, const std::string& oldAttributeValue)
|
||||
{
|
||||
if (attributeName != "name")
|
||||
return;
|
||||
ChildMap::iterator it = childMap.find (oldAttributeValue);
|
||||
if (it != childMap.end ())
|
||||
childMap.erase (it);
|
||||
const std::string* nameAttributeValue = node->getAttributes ()->getAttributeValue ("name");
|
||||
if (nameAttributeValue)
|
||||
childMap.emplace (*nameAttributeValue, node);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // Detail
|
||||
} // VSTGUI
|
||||
@@ -0,0 +1,76 @@
|
||||
// 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 "../../lib/cstring.h"
|
||||
#include "../../lib/vstguibase.h"
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace VSTGUI {
|
||||
namespace Detail {
|
||||
|
||||
class UINode;
|
||||
|
||||
using UIDescListContainerType = std::vector<UINode*>;
|
||||
//-----------------------------------------------------------------------------
|
||||
class UIDescList : public NonAtomicReferenceCounted, private UIDescListContainerType
|
||||
{
|
||||
public:
|
||||
using UIDescListContainerType::begin;
|
||||
using UIDescListContainerType::end;
|
||||
using UIDescListContainerType::rbegin;
|
||||
using UIDescListContainerType::rend;
|
||||
using UIDescListContainerType::iterator;
|
||||
using UIDescListContainerType::const_iterator;
|
||||
using UIDescListContainerType::const_reverse_iterator;
|
||||
using UIDescListContainerType::empty;
|
||||
using UIDescListContainerType::size;
|
||||
|
||||
explicit UIDescList (bool ownsObjects = true);
|
||||
UIDescList (const UIDescList& uiDesc);
|
||||
~UIDescList () noexcept override;
|
||||
|
||||
virtual void add (UINode* obj);
|
||||
virtual void remove (UINode* obj);
|
||||
virtual void removeAll ();
|
||||
virtual UINode* findChildNode (UTF8StringView nodeName) const;
|
||||
virtual UINode* findChildNodeWithAttributeValue (const std::string& attributeName,
|
||||
const std::string& attributeValue) const;
|
||||
|
||||
virtual void nodeAttributeChanged (UINode* child, const std::string& attributeName,
|
||||
const std::string& oldAttributeValue)
|
||||
{
|
||||
}
|
||||
|
||||
void sort ();
|
||||
|
||||
protected:
|
||||
bool ownsObjects;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class UIDescListWithFastFindAttributeNameChild : public UIDescList
|
||||
{
|
||||
private:
|
||||
using ChildMap = std::unordered_map<std::string, UINode*>;
|
||||
|
||||
public:
|
||||
UIDescListWithFastFindAttributeNameChild ();
|
||||
|
||||
void add (UINode* obj) override;
|
||||
void remove (UINode* obj) override;
|
||||
void removeAll () override;
|
||||
UINode* findChildNodeWithAttributeValue (const std::string& attributeName,
|
||||
const std::string& attributeValue) const override;
|
||||
void nodeAttributeChanged (UINode* node, const std::string& attributeName,
|
||||
const std::string& oldAttributeValue) override;
|
||||
|
||||
private:
|
||||
ChildMap childMap;
|
||||
};
|
||||
|
||||
} // Detail
|
||||
} // VSTGUI
|
||||
+744
@@ -0,0 +1,744 @@
|
||||
// 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 "../uiattributes.h"
|
||||
#include "uijsonpersistence.h"
|
||||
#include <array>
|
||||
#include <deque>
|
||||
#include <map>
|
||||
|
||||
#if __cplusplus > 201402L
|
||||
#include <string_view>
|
||||
#endif
|
||||
|
||||
#define RAPIDJSON_HAS_STDSTRING 1
|
||||
#if DEBUG
|
||||
#include "../../thirdparty/rapidjson/include/rapidjson/error/en.h"
|
||||
#endif
|
||||
#include "../../thirdparty/rapidjson/include/rapidjson/document.h"
|
||||
#include "../../thirdparty/rapidjson/include/rapidjson/prettywriter.h"
|
||||
#include "../../thirdparty/rapidjson/include/rapidjson/reader.h"
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace VSTGUI {
|
||||
namespace Detail {
|
||||
|
||||
static constexpr auto attributeNameStr = "name";
|
||||
static constexpr auto attributeValueStr = "value";
|
||||
static constexpr auto attributeClassStr = "class";
|
||||
static constexpr auto attributeTagStr = "tag";
|
||||
static constexpr auto attributeRGBAStr = "rgba";
|
||||
static constexpr auto keyDataStr = "data";
|
||||
static constexpr auto keyChildrenStr = "children";
|
||||
static constexpr auto keyTemplatesStr = "templates";
|
||||
static constexpr auto keyViewsStr = "views";
|
||||
static constexpr auto attributesStr = "attributes";
|
||||
static constexpr auto colorStr = "color";
|
||||
static constexpr auto controlTagStr = "control-tag";
|
||||
static constexpr auto bitmapStr = "bitmap";
|
||||
static constexpr auto fontStr = "font";
|
||||
static constexpr auto templateStr = "template";
|
||||
static constexpr auto colorStopStr = "color-stop";
|
||||
static constexpr auto viewStr = "view";
|
||||
static constexpr auto gradientStr = "gradient";
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace UIJsonDescReader {
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template <size_t size>
|
||||
struct ContentProviderWrapper
|
||||
{
|
||||
using Ch = uint8_t;
|
||||
|
||||
ContentProviderWrapper (IContentProvider& s) : stream (s)
|
||||
{
|
||||
bufferLeft = bufferSize = stream.readRawData (reinterpret_cast<int8_t*> (buffer.data ()),
|
||||
static_cast<int32_t> (buffer.size ()));
|
||||
if (bufferLeft == kStreamIOError)
|
||||
bufferSize = bufferLeft = 0;
|
||||
if (bufferSize == 0)
|
||||
{
|
||||
current = 0;
|
||||
bufferLeft = 1;
|
||||
}
|
||||
else
|
||||
current = buffer[bufferSize - bufferLeft];
|
||||
}
|
||||
|
||||
Ch Peek () const { return current; }
|
||||
Ch Take ()
|
||||
{
|
||||
auto result = Peek ();
|
||||
++pos;
|
||||
if (bufferLeft == 1)
|
||||
{
|
||||
bufferLeft = bufferSize = stream.readRawData (
|
||||
reinterpret_cast<int8_t*> (buffer.data ()), static_cast<int32_t> (buffer.size ()));
|
||||
if (bufferLeft == kStreamIOError)
|
||||
bufferSize = bufferLeft = 0;
|
||||
if (bufferSize == 0)
|
||||
{
|
||||
current = 0;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else
|
||||
--bufferLeft;
|
||||
current = buffer[bufferSize - bufferLeft];
|
||||
return result;
|
||||
}
|
||||
size_t Tell () { return pos; }
|
||||
|
||||
Ch* PutBegin ()
|
||||
{
|
||||
vstgui_assert (false);
|
||||
return 0;
|
||||
}
|
||||
void Put (Ch c) { vstgui_assert (false); }
|
||||
void Flush () { vstgui_assert (false); };
|
||||
size_t PutEnd (Ch* begin)
|
||||
{
|
||||
vstgui_assert (false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Ch current {};
|
||||
size_t pos {0};
|
||||
IContentProvider& stream;
|
||||
|
||||
std::array<Ch, size> buffer;
|
||||
size_t bufferLeft {};
|
||||
size_t bufferSize {};
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct Handler
|
||||
{
|
||||
using Ch = char;
|
||||
using SizeType = rapidjson::SizeType;
|
||||
|
||||
enum class State
|
||||
{
|
||||
Uninitialized = 0,
|
||||
Initialized,
|
||||
InRootNode,
|
||||
InBitmapRootNode,
|
||||
InFontRootNode,
|
||||
InColorRootNode,
|
||||
InGradientRootNode,
|
||||
InControlTagRootNode,
|
||||
InCustomRootNode,
|
||||
InVariableRootNode,
|
||||
InTemplateRootNode,
|
||||
BitmapNode,
|
||||
FontNode,
|
||||
GradientNode,
|
||||
TemplateNode,
|
||||
ChildrenNode,
|
||||
ViewNode,
|
||||
DataNode,
|
||||
ViewAttributes,
|
||||
};
|
||||
|
||||
bool Null () { return false; }
|
||||
bool Bool (bool b) { return false; }
|
||||
bool Int (int i) { return false; }
|
||||
bool Uint (unsigned i) { return false; }
|
||||
bool Int64 (int64_t i) { return false; }
|
||||
bool Uint64 (uint64_t i) { return false; }
|
||||
bool Double (double d) { return false; }
|
||||
bool RawNumber (const Ch* str, SizeType length, bool copy) { return false; }
|
||||
bool String (const Ch* str, SizeType length, bool copy)
|
||||
{
|
||||
if (state == State::InColorRootNode)
|
||||
{
|
||||
auto attrs = newAttributesWithNameAttr (keyStr);
|
||||
attrs->setAttribute (attributeRGBAStr, {str, length});
|
||||
nodeStack.back ()->getChildren ().add (new UIColorNode (colorStr, attrs));
|
||||
}
|
||||
else if (state == State::InControlTagRootNode)
|
||||
{
|
||||
auto attrs = newAttributesWithNameAttr (keyStr);
|
||||
attrs->setAttribute (attributeTagStr, {str, length});
|
||||
nodeStack.back ()->getChildren ().add (new UIControlTagNode (controlTagStr, attrs));
|
||||
}
|
||||
else if (state == State::InVariableRootNode)
|
||||
{
|
||||
auto attrs = newAttributesWithNameAttr (keyStr);
|
||||
attrs->setAttribute (attributeValueStr, {str, length});
|
||||
nodeStack.back ()->getChildren ().add (new UIVariableNode (controlTagStr, attrs));
|
||||
}
|
||||
else if (state == State::DataNode && keyStr == "data")
|
||||
{
|
||||
nodeStack.back ()->setData ({str, length});
|
||||
}
|
||||
else
|
||||
{
|
||||
nodeStack.back ()->getAttributes ()->setAttribute (keyStr, {str, length});
|
||||
}
|
||||
keyStr.clear ();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Key (const Ch* str, SizeType length, bool copy)
|
||||
{
|
||||
keyStr = {str, length};
|
||||
return true;
|
||||
}
|
||||
|
||||
bool StartObject ()
|
||||
{
|
||||
UINode* newNode = nullptr;
|
||||
State newState {};
|
||||
switch (state)
|
||||
{
|
||||
case State::Uninitialized:
|
||||
{
|
||||
newState = State::Initialized;
|
||||
break;
|
||||
}
|
||||
case State::Initialized:
|
||||
{
|
||||
vstgui_assert (keyStr == "vstgui-ui-description" ||
|
||||
keyStr == "vstgui-ui-description-view-list");
|
||||
rootNode = makeOwned<UINode> (std::move (keyStr));
|
||||
newNode = rootNode;
|
||||
newState = State::InRootNode;
|
||||
break;
|
||||
}
|
||||
case State::InRootNode:
|
||||
{
|
||||
if (keyStr == keyTemplatesStr || keyStr == keyViewsStr)
|
||||
{
|
||||
newState = State::InTemplateRootNode;
|
||||
break;
|
||||
}
|
||||
auto needsFastChildNameAttributeLookup = false;
|
||||
if (keyStr == MainNodeNames::kBitmap)
|
||||
{
|
||||
newState = State::InBitmapRootNode;
|
||||
needsFastChildNameAttributeLookup = true;
|
||||
}
|
||||
else if (keyStr == MainNodeNames::kFont)
|
||||
newState = State::InFontRootNode;
|
||||
else if (keyStr == MainNodeNames::kColor)
|
||||
{
|
||||
newState = State::InColorRootNode;
|
||||
needsFastChildNameAttributeLookup = true;
|
||||
}
|
||||
else if (keyStr == MainNodeNames::kGradient)
|
||||
newState = State::InGradientRootNode;
|
||||
else if (keyStr == MainNodeNames::kControlTag)
|
||||
{
|
||||
newState = State::InControlTagRootNode;
|
||||
needsFastChildNameAttributeLookup = true;
|
||||
}
|
||||
else if (keyStr == MainNodeNames::kCustom)
|
||||
newState = State::InCustomRootNode;
|
||||
else if (keyStr == MainNodeNames::kVariable)
|
||||
newState = State::InVariableRootNode;
|
||||
else
|
||||
return false;
|
||||
newNode = new UINode (keyStr, nullptr, needsFastChildNameAttributeLookup);
|
||||
break;
|
||||
}
|
||||
case State::InBitmapRootNode:
|
||||
{
|
||||
newNode = new UIBitmapNode (bitmapStr, newAttributesWithNameAttr (keyStr));
|
||||
newState = State::BitmapNode;
|
||||
break;
|
||||
}
|
||||
case State::InFontRootNode:
|
||||
{
|
||||
newNode = new UIFontNode (fontStr, newAttributesWithNameAttr (keyStr));
|
||||
newState = State::FontNode;
|
||||
break;
|
||||
}
|
||||
case State::InCustomRootNode:
|
||||
{
|
||||
newNode = new UINode (attributesStr, newAttributesWithNameAttr (keyStr));
|
||||
newState = State::DataNode;
|
||||
break;
|
||||
}
|
||||
case State::InTemplateRootNode:
|
||||
{
|
||||
newNode = new UINode (templateStr, newAttributesWithNameAttr (keyStr));
|
||||
newState = State::TemplateNode;
|
||||
break;
|
||||
}
|
||||
case State::BitmapNode:
|
||||
{
|
||||
vstgui_assert (keyStr == keyDataStr);
|
||||
newNode = new UINode (keyStr);
|
||||
newState = State::DataNode;
|
||||
break;
|
||||
}
|
||||
case State::GradientNode:
|
||||
{
|
||||
vstgui_assert (keyStr.empty ());
|
||||
newNode = new UINode (colorStopStr);
|
||||
newState = State::DataNode;
|
||||
break;
|
||||
}
|
||||
case State::TemplateNode:
|
||||
{
|
||||
if (keyStr == attributesStr)
|
||||
newState = State::ViewAttributes;
|
||||
else if (keyStr == keyChildrenStr)
|
||||
newState = State::ChildrenNode;
|
||||
break;
|
||||
}
|
||||
case State::ChildrenNode:
|
||||
{
|
||||
auto attr = makeOwned<UIAttributes> (15);
|
||||
newNode = new UINode (viewStr, attr);
|
||||
newState = State::ViewNode;
|
||||
break;
|
||||
}
|
||||
case State::ViewNode:
|
||||
{
|
||||
newState = State::ChildrenNode;
|
||||
break;
|
||||
}
|
||||
case State::InColorRootNode:
|
||||
case State::InControlTagRootNode:
|
||||
case State::InVariableRootNode:
|
||||
case State::InGradientRootNode:
|
||||
case State::FontNode:
|
||||
case State::DataNode:
|
||||
case State::ViewAttributes:
|
||||
{
|
||||
// not allowed here, invalid JSON data!
|
||||
return false;
|
||||
}
|
||||
}
|
||||
keyStr.clear ();
|
||||
pushNode (newNode);
|
||||
pushState (newState);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EndObject (SizeType memberCount)
|
||||
{
|
||||
if (state == State::InTemplateRootNode || state == State::ChildrenNode ||
|
||||
state == State::ViewAttributes)
|
||||
{
|
||||
popState ();
|
||||
return true;
|
||||
}
|
||||
popState ();
|
||||
return popNode ();
|
||||
}
|
||||
|
||||
bool StartArray ()
|
||||
{
|
||||
if (state == State::InGradientRootNode)
|
||||
{
|
||||
auto newNode = new UIGradientNode (gradientStr, newAttributesWithNameAttr (keyStr));
|
||||
pushNode (newNode);
|
||||
pushState (State::GradientNode);
|
||||
keyStr.clear ();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EndArray (SizeType elementCount)
|
||||
{
|
||||
if (state != State::GradientNode)
|
||||
return false;
|
||||
popState ();
|
||||
if (!popNode ())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool popNode ()
|
||||
{
|
||||
if (nodeStack.empty ())
|
||||
return state == State::Uninitialized;
|
||||
nodeStack.pop_back ();
|
||||
return true;
|
||||
}
|
||||
|
||||
void pushNode (UINode* newNode)
|
||||
{
|
||||
if (newNode)
|
||||
{
|
||||
if (newNode != rootNode)
|
||||
nodeStack.back ()->getChildren ().add (newNode);
|
||||
nodeStack.emplace_back (newNode);
|
||||
}
|
||||
}
|
||||
|
||||
void popState ()
|
||||
{
|
||||
stateStack.pop_back ();
|
||||
state = stateStack.back ();
|
||||
}
|
||||
|
||||
void pushState (State newState)
|
||||
{
|
||||
stateStack.emplace_back (newState);
|
||||
state = newState;
|
||||
}
|
||||
|
||||
static SharedPointer<UIAttributes> newAttributesWithNameAttr (const std::string& name)
|
||||
{
|
||||
auto attributes = makeOwned<UIAttributes> ();
|
||||
attributes->setAttribute (attributeNameStr, name);
|
||||
return attributes;
|
||||
}
|
||||
|
||||
SharedPointer<UINode> rootNode;
|
||||
std::deque<UINode*> nodeStack;
|
||||
std::deque<State> stateStack {State::Uninitialized};
|
||||
State state {};
|
||||
std::string keyStr;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
SharedPointer<UINode> read (IContentProvider& stream)
|
||||
{
|
||||
ContentProviderWrapper<1024> streamWrapper (stream);
|
||||
Handler handler;
|
||||
rapidjson::Reader reader;
|
||||
|
||||
auto result = reader.Parse<rapidjson::kParseStopWhenDoneFlag> (streamWrapper, handler);
|
||||
if (result.IsError ())
|
||||
{
|
||||
#if DEBUG
|
||||
DebugPrint ("JSON Parsing Error:");
|
||||
if (auto errorString = rapidjson::GetParseError_En (result.Code ()))
|
||||
DebugPrint (" %s", errorString);
|
||||
else
|
||||
DebugPrint (" %d", result.Code ());
|
||||
DebugPrint ("\n\tAt byte offset: %d\n", result.Offset ());
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
return handler.rootNode;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // UIJsonDescReader
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace UIJsonDescWriter {
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template <typename CharT>
|
||||
struct OutputStreamWrapper
|
||||
{
|
||||
using Ch = CharT;
|
||||
|
||||
OutputStreamWrapper (OutputStream& stream) : stream (stream) {}
|
||||
|
||||
void Put (CharT c) { stream << c; }
|
||||
void Flush () {}
|
||||
|
||||
OutputStream& stream;
|
||||
};
|
||||
|
||||
using DefaultOutputStreamWrapper = OutputStreamWrapper<uint8_t>;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static const std::string* getNodeAttributeName (const UINode* node)
|
||||
{
|
||||
if (auto attributes = node->getAttributes ())
|
||||
return attributes->getAttributeValue (attributeNameStr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static const std::string* getNodeAttributeViewClass (const UINode* node)
|
||||
{
|
||||
if (auto attributes = node->getAttributes ())
|
||||
return attributes->getAttributeValue (attributeClassStr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template <typename JSONWriter>
|
||||
void writeAttributes (const UIAttributes& attributes, JSONWriter& writer,
|
||||
bool ignoreNameAttribute = false)
|
||||
{
|
||||
#if __cplusplus > 201402L
|
||||
std::map<std::string_view, std::string_view> ordered (attributes.begin (), attributes.end ());
|
||||
#else
|
||||
std::map<std::string, std::string> ordered (attributes.begin (), attributes.end ());
|
||||
#endif
|
||||
for (const auto& attr : ordered)
|
||||
{
|
||||
if (ignoreNameAttribute && attr.first == attributeNameStr)
|
||||
continue;
|
||||
if (attr.second.empty ()) // don't write empty attributes
|
||||
continue;
|
||||
writer.Key (attr.first.data (), static_cast<rapidjson::SizeType> (attr.first.size ()));
|
||||
writer.String (attr.second.data (), static_cast<rapidjson::SizeType> (attr.second.size ()));
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template <typename JSONWriter>
|
||||
void writeNode (const UINode* node, JSONWriter& writer)
|
||||
{
|
||||
auto name = getNodeAttributeName (node);
|
||||
if (name)
|
||||
writer.Key (*name);
|
||||
writer.StartObject ();
|
||||
writeAttributes (*node->getAttributes (), writer, name != nullptr);
|
||||
for (const auto& child : node->getChildren ())
|
||||
{
|
||||
writer.Key (child->getName ());
|
||||
writer.StartObject ();
|
||||
writeAttributes (*child->getAttributes (), writer);
|
||||
if (child->getData ().empty () == false)
|
||||
{
|
||||
writer.Key (keyDataStr);
|
||||
writer.String (child->getData ());
|
||||
}
|
||||
vstgui_assert (child->getChildren ().empty ());
|
||||
writer.EndObject ();
|
||||
}
|
||||
writer.EndObject ();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template <typename JSONWriter>
|
||||
void writeGradientNode (const UINode* node, JSONWriter& writer)
|
||||
{
|
||||
auto name = getNodeAttributeName (node);
|
||||
vstgui_assert (name);
|
||||
writer.Key (*name);
|
||||
writer.StartArray ();
|
||||
for (const auto& child : node->getChildren ())
|
||||
{
|
||||
writer.StartObject ();
|
||||
writeAttributes (*child->getAttributes (), writer);
|
||||
vstgui_assert (child->getChildren ().empty ());
|
||||
writer.EndObject ();
|
||||
}
|
||||
writer.EndArray ();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template <typename JSONWriter>
|
||||
void writeSingleAttributeNode (const char* attrName, const UINode* node, JSONWriter& writer)
|
||||
{
|
||||
auto name = getNodeAttributeName (node);
|
||||
vstgui_assert (name);
|
||||
writer.Key (*name);
|
||||
vstgui_assert (node->getAttributes ());
|
||||
if (auto tag = node->getAttributes ()->getAttributeValue (attrName))
|
||||
writer.String (*tag);
|
||||
else
|
||||
writer.String ("");
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template <typename JSONWriter>
|
||||
void writeColorAttributeNode (const UINode* node, JSONWriter& writer)
|
||||
{
|
||||
auto name = getNodeAttributeName (node);
|
||||
vstgui_assert (name);
|
||||
writer.Key (*name);
|
||||
vstgui_assert (node->getAttributes ());
|
||||
if (auto color = node->getAttributes ()->getAttributeValue (attributeRGBAStr))
|
||||
{
|
||||
writer.String (*color);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto colorNode = dynamic_cast<const UIColorNode*> (node);
|
||||
vstgui_assert (colorNode);
|
||||
writer.String (colorNode->getColor ().toString ().getString ());
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template <typename JSONWriter, typename Proc>
|
||||
void writeResourceNode (const char* name, const UINode* resNode, Proc proc, JSONWriter& writer)
|
||||
{
|
||||
writer.Key (name);
|
||||
writer.StartObject ();
|
||||
if (resNode->getAttributes () && resNode->getAttributes ()->empty () == false)
|
||||
writeAttributes (*resNode->getAttributes (), writer);
|
||||
for (auto& child : resNode->getChildren ())
|
||||
{
|
||||
if (child->noExport () == false)
|
||||
proc (child, writer);
|
||||
}
|
||||
writer.EndObject ();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template <typename JSONWriter>
|
||||
void writeTemplateNode (const std::string* name, const UINode* node, JSONWriter& writer)
|
||||
{
|
||||
if (name)
|
||||
writer.Key (*name);
|
||||
writer.StartObject ();
|
||||
writer.String (attributesStr);
|
||||
writer.StartObject ();
|
||||
writeAttributes (*node->getAttributes (), writer, name != nullptr);
|
||||
writer.EndObject ();
|
||||
if (node->getChildren ().empty () == false)
|
||||
{
|
||||
writer.Key (keyChildrenStr);
|
||||
writer.StartObject ();
|
||||
for (const auto& child : node->getChildren ())
|
||||
{
|
||||
writeTemplateNode (getNodeAttributeViewClass (child), child, writer);
|
||||
}
|
||||
writer.EndObject ();
|
||||
}
|
||||
writer.EndObject ();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template <typename JSONWriter>
|
||||
void writeViewNodes (const std::vector<const UINode*>& views, JSONWriter& writer)
|
||||
{
|
||||
if (views.empty ())
|
||||
return;
|
||||
writer.Key (keyViewsStr);
|
||||
writer.StartObject ();
|
||||
for (auto& child : views)
|
||||
{
|
||||
writeTemplateNode (getNodeAttributeViewClass (child), child, writer);
|
||||
}
|
||||
writer.EndObject ();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template <typename JSONWriter>
|
||||
void writeTemplates (const std::vector<const UINode*>& templates, JSONWriter& writer)
|
||||
{
|
||||
if (templates.empty ())
|
||||
return;
|
||||
writer.Key (keyTemplatesStr);
|
||||
writer.StartObject ();
|
||||
for (auto& child : templates)
|
||||
{
|
||||
writeTemplateNode (getNodeAttributeName (child), child, writer);
|
||||
}
|
||||
writer.EndObject ();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template <typename JSONWriter>
|
||||
bool writeRootNode (UINode* rootNode, JSONWriter& writer)
|
||||
{
|
||||
writer.StartObject ();
|
||||
writer.Key (rootNode->getName ());
|
||||
writer.StartObject ();
|
||||
writeAttributes (*rootNode->getAttributes (), writer);
|
||||
bool result = true;
|
||||
std::vector<const UINode*> templateNodes;
|
||||
std::vector<const UINode*> viewNodes;
|
||||
const UINode* bitmapsNode = nullptr;
|
||||
const UINode* fontsNode = nullptr;
|
||||
const UINode* colorsNode = nullptr;
|
||||
const UINode* controlTagsNode = nullptr;
|
||||
const UINode* variablesNode = nullptr;
|
||||
const UINode* gradientsNode = nullptr;
|
||||
const UINode* customNode = nullptr;
|
||||
for (const auto& child : rootNode->getChildren ())
|
||||
{
|
||||
if (child->getName () == MainNodeNames::kTemplate)
|
||||
templateNodes.emplace_back (child);
|
||||
else if (child->getName () == MainNodeNames::kBitmap)
|
||||
bitmapsNode = child;
|
||||
else if (child->getName () == MainNodeNames::kFont)
|
||||
fontsNode = child;
|
||||
else if (child->getName () == MainNodeNames::kColor)
|
||||
colorsNode = child;
|
||||
else if (child->getName () == MainNodeNames::kControlTag)
|
||||
controlTagsNode = child;
|
||||
else if (child->getName () == MainNodeNames::kVariable)
|
||||
variablesNode = child;
|
||||
else if (child->getName () == MainNodeNames::kGradient)
|
||||
gradientsNode = child;
|
||||
else if (child->getName () == MainNodeNames::kCustom)
|
||||
customNode = child;
|
||||
else if (child->getName () == viewStr)
|
||||
viewNodes.emplace_back (child);
|
||||
else if (child->getName () == "comment")
|
||||
{
|
||||
// comments are removed
|
||||
continue;
|
||||
}
|
||||
else
|
||||
return false; // unexpected input
|
||||
}
|
||||
if (variablesNode)
|
||||
{
|
||||
writeResourceNode (MainNodeNames::kVariable, variablesNode,
|
||||
[] (UINode* node, JSONWriter& writer) {
|
||||
writeSingleAttributeNode (attributeValueStr, node, writer);
|
||||
},
|
||||
writer);
|
||||
}
|
||||
if (bitmapsNode)
|
||||
{
|
||||
writeResourceNode (MainNodeNames::kBitmap, bitmapsNode, writeNode<JSONWriter>, writer);
|
||||
}
|
||||
if (fontsNode)
|
||||
{
|
||||
writeResourceNode (MainNodeNames::kFont, fontsNode, writeNode<JSONWriter>, writer);
|
||||
}
|
||||
if (colorsNode)
|
||||
{
|
||||
writeResourceNode (MainNodeNames::kColor, colorsNode, writeColorAttributeNode<JSONWriter>,
|
||||
writer);
|
||||
}
|
||||
if (gradientsNode)
|
||||
{
|
||||
writeResourceNode (MainNodeNames::kGradient, gradientsNode, writeGradientNode<JSONWriter>,
|
||||
writer);
|
||||
}
|
||||
if (controlTagsNode)
|
||||
{
|
||||
writeResourceNode (MainNodeNames::kControlTag, controlTagsNode,
|
||||
[] (UINode* node, JSONWriter& writer) {
|
||||
writeSingleAttributeNode (attributeTagStr, node, writer);
|
||||
},
|
||||
writer);
|
||||
}
|
||||
if (customNode)
|
||||
{
|
||||
writeResourceNode (MainNodeNames::kCustom, customNode, writeNode<JSONWriter>, writer);
|
||||
}
|
||||
writeViewNodes (viewNodes, writer);
|
||||
writeTemplates (templateNodes, writer);
|
||||
writer.EndObject ();
|
||||
writer.EndObject ();
|
||||
return result;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool write (OutputStream& stream, UINode* rootNode, bool pretty)
|
||||
{
|
||||
DefaultOutputStreamWrapper output (stream);
|
||||
|
||||
if (pretty)
|
||||
{
|
||||
rapidjson::PrettyWriter<DefaultOutputStreamWrapper> writer (output);
|
||||
writer.SetIndent ('\t', 1);
|
||||
auto result = writeRootNode (rootNode, writer);
|
||||
return result;
|
||||
}
|
||||
rapidjson::Writer<DefaultOutputStreamWrapper> writer (output);
|
||||
auto result = writeRootNode (rootNode, writer);
|
||||
return result;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // UIJsonDescWriter
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // Detail
|
||||
} // VSTGUI
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
// 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 "../cstream.h"
|
||||
#include "../icontentprovider.h"
|
||||
#include "uinode.h"
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace VSTGUI {
|
||||
namespace Detail {
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace UIJsonDescReader {
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
SharedPointer<UINode> read (IContentProvider& contentProvider);
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // UIJsonDescReader
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace UIJsonDescWriter {
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool write (OutputStream& stream, UINode* rootNode, bool pretty = true);
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // UIJsonDescWriter
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // Detail
|
||||
} // VSTGUI
|
||||
@@ -0,0 +1,742 @@
|
||||
// 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 "../../lib/cbitmap.h"
|
||||
#include "../../lib/cfont.h"
|
||||
#include "../../lib/cgradient.h"
|
||||
#include "../../lib/platform/platformfactory.h"
|
||||
#include "../base64codec.h"
|
||||
#include "../cstream.h"
|
||||
#include "../uiattributes.h"
|
||||
#include "../uiviewcreator.h"
|
||||
#include "locale.h"
|
||||
#include "parsecolor.h"
|
||||
#include "scalefactorutils.h"
|
||||
#include "uinode.h"
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
namespace VSTGUI {
|
||||
namespace Detail {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
UINode::UINode (const std::string& _name, const SharedPointer<UIAttributes>& _attributes,
|
||||
bool needsFastChildNameAttributeLookup)
|
||||
: name (_name), attributes (_attributes), flags (0)
|
||||
{
|
||||
if (needsFastChildNameAttributeLookup)
|
||||
children = makeOwned<UIDescListWithFastFindAttributeNameChild> ();
|
||||
else
|
||||
children = makeOwned<UIDescList> ();
|
||||
if (attributes == nullptr)
|
||||
attributes = makeOwned<UIAttributes> ();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
UINode::UINode (const std::string& _name, const SharedPointer<UIDescList>& _children,
|
||||
const SharedPointer<UIAttributes>& _attributes)
|
||||
: name (_name), attributes (_attributes), children (_children), flags (0)
|
||||
{
|
||||
vstgui_assert (children != nullptr);
|
||||
if (attributes == nullptr)
|
||||
attributes = makeOwned<UIAttributes> ();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
UINode::UINode (const UINode& n)
|
||||
: name (n.name)
|
||||
, data (n.data)
|
||||
, attributes (makeOwned<UIAttributes> (*n.attributes))
|
||||
, children (makeOwned<UIDescList> (*n.children))
|
||||
, flags (n.flags)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
UINode::~UINode () noexcept
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool UINode::hasChildren () const
|
||||
{
|
||||
return !children->empty ();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void UINode::childAttributeChanged (UINode* child, const char* attributeName,
|
||||
const char* oldAttributeValue)
|
||||
{
|
||||
children->nodeAttributeChanged (child, attributeName, oldAttributeValue);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void UINode::sortChildren ()
|
||||
{
|
||||
children->sort ();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void UINode::setData (DataStorage&& newData)
|
||||
{
|
||||
data = std::move (newData);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
UICommentNode::UICommentNode (const std::string& comment) : UINode ("comment")
|
||||
{
|
||||
data = comment;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
UIVariableNode::UIVariableNode (const std::string& name,
|
||||
const SharedPointer<UIAttributes>& attributes)
|
||||
: UINode (name, attributes), type (kUnknown), number (0)
|
||||
{
|
||||
const std::string* typeStr = attributes->getAttributeValue ("type");
|
||||
const std::string* valueStr = attributes->getAttributeValue ("value");
|
||||
if (typeStr)
|
||||
{
|
||||
if (*typeStr == "number")
|
||||
type = kNumber;
|
||||
else if (*typeStr == "string")
|
||||
type = kString;
|
||||
}
|
||||
if (valueStr)
|
||||
{
|
||||
Detail::Locale localeResetter;
|
||||
|
||||
const char* strPtr = valueStr->c_str ();
|
||||
if (type == kUnknown)
|
||||
{
|
||||
char* endPtr = nullptr;
|
||||
double numberCheck = strtod (strPtr, &endPtr);
|
||||
if (endPtr == strPtr + strlen (strPtr))
|
||||
{
|
||||
number = numberCheck;
|
||||
type = kNumber;
|
||||
}
|
||||
else
|
||||
type = kString;
|
||||
}
|
||||
else if (type == kNumber)
|
||||
{
|
||||
number = strtod (strPtr, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
UIVariableNode::Type UIVariableNode::getType () const
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
double UIVariableNode::getNumber () const
|
||||
{
|
||||
return number;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
const std::string& UIVariableNode::getString () const
|
||||
{
|
||||
const std::string* value = attributes->getAttributeValue ("value");
|
||||
if (value)
|
||||
return *value;
|
||||
static std::string kEmpty;
|
||||
return kEmpty;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
UIControlTagNode::UIControlTagNode (const std::string& name,
|
||||
const SharedPointer<UIAttributes>& attributes)
|
||||
: UINode (name, attributes), tag (-1)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int32_t UIControlTagNode::getTag ()
|
||||
{
|
||||
if (tag == -1)
|
||||
{
|
||||
const std::string* tagStr = attributes->getAttributeValue ("tag");
|
||||
if (tagStr)
|
||||
{
|
||||
if (tagStr->size () == 6 && (*tagStr)[0] == '\'' && (*tagStr)[5] == '\'')
|
||||
{
|
||||
char c1 = (*tagStr)[1];
|
||||
char c2 = (*tagStr)[2];
|
||||
char c3 = (*tagStr)[3];
|
||||
char c4 = (*tagStr)[4];
|
||||
tag = ((((int32_t)c1) << 24) | (((int32_t)c2) << 16) | (((int32_t)c3) << 8) |
|
||||
(((int32_t)c4) << 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
char* endPtr = nullptr;
|
||||
tag = (int32_t)strtol (tagStr->c_str (), &endPtr, 10);
|
||||
if (endPtr != tagStr->c_str () + tagStr->length ())
|
||||
tag = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void UIControlTagNode::setTag (int32_t newTag)
|
||||
{
|
||||
tag = newTag;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
const std::string* UIControlTagNode::getTagString () const
|
||||
{
|
||||
return attributes->getAttributeValue ("tag");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void UIControlTagNode::setTagString (const std::string& str)
|
||||
{
|
||||
attributes->setAttribute ("tag", str);
|
||||
tag = -1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
UIBitmapNode::UIBitmapNode (const std::string& name, const SharedPointer<UIAttributes>& attributes)
|
||||
: UINode (name, attributes), bitmap (nullptr), filterProcessed (false), scaledBitmapsAdded (false)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
UIBitmapNode::~UIBitmapNode () noexcept
|
||||
{
|
||||
if (bitmap)
|
||||
bitmap->forget ();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void UIBitmapNode::freePlatformResources ()
|
||||
{
|
||||
if (bitmap)
|
||||
bitmap->forget ();
|
||||
bitmap = nullptr;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool UIBitmapNode::imagesEqual (IPlatformBitmap* b1, IPlatformBitmap* b2)
|
||||
{
|
||||
if (b1 == b2)
|
||||
return true;
|
||||
if (b1->getSize () != b2->getSize () || b1->getScaleFactor () != b2->getScaleFactor ())
|
||||
return false;
|
||||
auto ac1 = b1->lockPixels (true);
|
||||
if (!ac1)
|
||||
return false;
|
||||
auto ac2 = b2->lockPixels (true);
|
||||
if (!ac2)
|
||||
return false;
|
||||
auto rowBytes = ac1->getBytesPerRow ();
|
||||
if (rowBytes != ac2->getBytesPerRow ())
|
||||
return false;
|
||||
if (ac1->getPixelFormat () != ac2->getPixelFormat ())
|
||||
return false;
|
||||
auto adr1 = ac1->getAddress ();
|
||||
if (!adr1)
|
||||
return false;
|
||||
auto adr2 = ac2->getAddress ();
|
||||
if (!adr2)
|
||||
return false;
|
||||
uint32_t rows = static_cast<uint32_t> (b1->getSize ().y);
|
||||
for (uint32_t y = 0; y < rows; ++y, adr1 += rowBytes, adr2 += rowBytes)
|
||||
{
|
||||
if (memcmp (adr1, adr2, rowBytes) != 0)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool UIBitmapNode::hasXMLData () const
|
||||
{
|
||||
return getChildren ().findChildNode ("data") != nullptr;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void UIBitmapNode::createXMLData (const std::string& pathHint)
|
||||
{
|
||||
UINode* node = getChildren ().findChildNode ("data");
|
||||
if (node)
|
||||
{
|
||||
if (node->getData ().empty ())
|
||||
{
|
||||
getChildren ().remove (node);
|
||||
node = nullptr;
|
||||
}
|
||||
else if (auto bm = getBitmap (pathHint))
|
||||
{
|
||||
if (auto platformBitmap = bm->getPlatformBitmap ())
|
||||
{
|
||||
if (auto dataBitmap = createBitmapFromDataNode ())
|
||||
{
|
||||
if (!imagesEqual (platformBitmap, dataBitmap))
|
||||
{
|
||||
removeXMLData ();
|
||||
node = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node == nullptr)
|
||||
{
|
||||
if (auto bm = getBitmap (pathHint))
|
||||
{
|
||||
if (auto platformBitmap = bm->getPlatformBitmap ())
|
||||
{
|
||||
auto buffer =
|
||||
getPlatformFactory ().createBitmapMemoryPNGRepresentation (platformBitmap);
|
||||
if (!buffer.empty ())
|
||||
{
|
||||
auto result = Base64Codec::encode (buffer.data (),
|
||||
static_cast<uint32_t> (buffer.size ()));
|
||||
UINode* dataNode = new UINode ("data");
|
||||
dataNode->getAttributes ()->setAttribute ("encoding", "base64");
|
||||
dataNode->getData ().append (reinterpret_cast<const char*> (result.data.get ()),
|
||||
static_cast<std::streamsize> (result.dataSize));
|
||||
getChildren ().add (dataNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void UIBitmapNode::removeXMLData ()
|
||||
{
|
||||
UINode* node = getChildren ().findChildNode ("data");
|
||||
if (node)
|
||||
getChildren ().remove (node);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
CBitmap* UIBitmapNode::createBitmap (const std::string& str, const BitmapVariant& variant) const
|
||||
{
|
||||
|
||||
if (auto partDesc = std::get_if<CNinePartTiledDescription> (&variant))
|
||||
return new CNinePartTiledBitmap (CResourceDescription (str.data ()), *partDesc);
|
||||
else if (auto multiFrameDesc = std::get_if<CMultiFrameBitmapDescription> (&variant))
|
||||
return new CMultiFrameBitmap (CResourceDescription (str.data ()), *multiFrameDesc);
|
||||
return new CBitmap (CResourceDescription (str.c_str ()));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
UINode* UIBitmapNode::dataNode () const
|
||||
{
|
||||
UINode* node = getChildren ().findChildNode ("data");
|
||||
return (node && !node->getData ().empty ()) ? node : nullptr;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
PlatformBitmapPtr UIBitmapNode::createBitmapFromDataNode () const
|
||||
{
|
||||
if (auto node = dataNode ())
|
||||
{
|
||||
auto codecStr = node->getAttributes ()->getAttributeValue ("encoding");
|
||||
if (codecStr && *codecStr == "base64")
|
||||
{
|
||||
auto result = Base64Codec::decode (node->getData ());
|
||||
if (auto platformBitmap = getPlatformFactory ().createBitmapFromMemory (
|
||||
result.data.get (), result.dataSize))
|
||||
{
|
||||
double scaleFactor = 1.;
|
||||
if (attributes->getDoubleAttribute ("scale-factor", scaleFactor))
|
||||
platformBitmap->setScaleFactor (scaleFactor);
|
||||
return platformBitmap;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
CBitmap* UIBitmapNode::getBitmap (const std::string& pathHint)
|
||||
{
|
||||
if (bitmap == nullptr)
|
||||
{
|
||||
const std::string* path = attributes->getAttributeValue ("path");
|
||||
if (path)
|
||||
{
|
||||
BitmapVariant bitmapVariant;
|
||||
int32_t tmpValue {};
|
||||
CRect offsets;
|
||||
if (attributes->getRectAttribute ("nineparttiled-offsets", offsets))
|
||||
{
|
||||
bitmapVariant = CNinePartTiledDescription (offsets.left, offsets.top, offsets.right,
|
||||
offsets.bottom);
|
||||
}
|
||||
else if (attributes->getIntegerAttribute ("multiframe-num-frames", tmpValue))
|
||||
{
|
||||
CMultiFrameBitmapDescription multiFrameDesc {};
|
||||
multiFrameDesc.numFrames = static_cast<uint16_t> (tmpValue);
|
||||
if (attributes->getIntegerAttribute ("mulitframe-frames-per-row", tmpValue))
|
||||
multiFrameDesc.framesPerRow = static_cast<uint16_t> (tmpValue);
|
||||
attributes->getPointAttribute ("multiframe-size", multiFrameDesc.frameSize);
|
||||
bitmapVariant = multiFrameDesc;
|
||||
}
|
||||
bitmap = createBitmap (*path, bitmapVariant);
|
||||
if (bitmap->getPlatformBitmap () == nullptr && pathIsAbsolute (pathHint))
|
||||
{
|
||||
std::string absPath = pathHint;
|
||||
if (removeLastPathComponent (absPath))
|
||||
{
|
||||
absPath += "/" + *path;
|
||||
if (auto platformBitmap =
|
||||
getPlatformFactory ().createBitmapFromPath (absPath.c_str ()))
|
||||
{
|
||||
bitmap->setPlatformBitmap (platformBitmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bitmap && bitmap->getPlatformBitmap () == nullptr)
|
||||
{
|
||||
if (auto platformBitmap = createBitmapFromDataNode ())
|
||||
bitmap->setPlatformBitmap (platformBitmap);
|
||||
}
|
||||
if (bitmap && path && bitmap->getPlatformBitmap () &&
|
||||
bitmap->getPlatformBitmap ()->getScaleFactor () == 1.)
|
||||
{
|
||||
double scaleFactor = 1.;
|
||||
if (Detail::decodeScaleFactorFromName (*path, scaleFactor))
|
||||
{
|
||||
bitmap->getPlatformBitmap ()->setScaleFactor (scaleFactor);
|
||||
attributes->setDoubleAttribute ("scale-factor", scaleFactor);
|
||||
}
|
||||
}
|
||||
}
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void UIBitmapNode::setBitmap (UTF8StringPtr bitmapName)
|
||||
{
|
||||
std::string name (bitmapName);
|
||||
attributes->setAttribute ("path", name);
|
||||
if (bitmap)
|
||||
bitmap->forget ();
|
||||
bitmap = nullptr;
|
||||
double scaleFactor = 1.;
|
||||
if (Detail::decodeScaleFactorFromName (name, scaleFactor))
|
||||
attributes->setDoubleAttribute ("scale-factor", scaleFactor);
|
||||
removeXMLData ();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void UIBitmapNode::setMultiFrameDesc (const CMultiFrameBitmapDescription* desc)
|
||||
{
|
||||
if (bitmap)
|
||||
{
|
||||
if (auto mfb = dynamic_cast<CMultiFrameBitmap*> (bitmap); mfb && desc)
|
||||
{
|
||||
mfb->setMultiFrameDesc (*desc);
|
||||
}
|
||||
else
|
||||
{
|
||||
bitmap->forget ();
|
||||
bitmap = nullptr;
|
||||
}
|
||||
}
|
||||
if (desc)
|
||||
{
|
||||
attributes->setPointAttribute ("multiframe-size", desc->frameSize);
|
||||
attributes->setIntegerAttribute ("multiframe-num-frames", desc->numFrames);
|
||||
attributes->setIntegerAttribute ("mulitframe-frames-per-row", desc->framesPerRow);
|
||||
}
|
||||
else
|
||||
{
|
||||
attributes->removeAttribute ("multiframe-size");
|
||||
attributes->removeAttribute ("multiframe-num-frames");
|
||||
attributes->removeAttribute ("mulitframe-frames-per-row");
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void UIBitmapNode::setNinePartTiledOffset (const CRect* offsets)
|
||||
{
|
||||
if (bitmap)
|
||||
{
|
||||
auto* tiledBitmap = dynamic_cast<CNinePartTiledBitmap*> (bitmap);
|
||||
if (offsets && tiledBitmap)
|
||||
{
|
||||
tiledBitmap->setPartOffsets (CNinePartTiledDescription (
|
||||
offsets->left, offsets->top, offsets->right, offsets->bottom));
|
||||
}
|
||||
else
|
||||
{
|
||||
bitmap->forget ();
|
||||
bitmap = nullptr;
|
||||
}
|
||||
}
|
||||
if (offsets)
|
||||
attributes->setRectAttribute ("nineparttiled-offsets", *offsets);
|
||||
else
|
||||
attributes->removeAttribute ("nineparttiled-offsets");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void UIBitmapNode::invalidBitmap ()
|
||||
{
|
||||
if (bitmap)
|
||||
bitmap->forget ();
|
||||
bitmap = nullptr;
|
||||
filterProcessed = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
UIFontNode::UIFontNode (const std::string& name, const SharedPointer<UIAttributes>& attributes)
|
||||
: UINode (name, attributes), font (nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
UIFontNode::~UIFontNode () noexcept
|
||||
{
|
||||
if (font)
|
||||
font->forget ();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void UIFontNode::freePlatformResources ()
|
||||
{
|
||||
if (font)
|
||||
font->forget ();
|
||||
font = nullptr;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
CFontRef UIFontNode::getFont ()
|
||||
{
|
||||
if (font == nullptr)
|
||||
{
|
||||
const std::string* nameAttr = attributes->getAttributeValue ("font-name");
|
||||
const std::string* sizeAttr = attributes->getAttributeValue ("size");
|
||||
const std::string* boldAttr = attributes->getAttributeValue ("bold");
|
||||
const std::string* italicAttr = attributes->getAttributeValue ("italic");
|
||||
const std::string* underlineAttr = attributes->getAttributeValue ("underline");
|
||||
const std::string* strikethroughAttr = attributes->getAttributeValue ("strike-through");
|
||||
if (nameAttr)
|
||||
{
|
||||
int32_t size = 12;
|
||||
if (sizeAttr)
|
||||
size = (int32_t)strtol (sizeAttr->c_str (), nullptr, 10);
|
||||
int32_t fontStyle = 0;
|
||||
if (boldAttr && *boldAttr == "true")
|
||||
fontStyle |= kBoldFace;
|
||||
if (italicAttr && *italicAttr == "true")
|
||||
fontStyle |= kItalicFace;
|
||||
if (underlineAttr && *underlineAttr == "true")
|
||||
fontStyle |= kUnderlineFace;
|
||||
if (strikethroughAttr && *strikethroughAttr == "true")
|
||||
fontStyle |= kStrikethroughFace;
|
||||
if (attributes->hasAttribute ("alternative-font-names"))
|
||||
{
|
||||
std::list<std::string> fontNames;
|
||||
getPlatformFactory ().getAllFontFamilies ([&fontNames] (const std::string& name) {
|
||||
fontNames.push_back (name);
|
||||
return true;
|
||||
});
|
||||
if (std::find (fontNames.begin (), fontNames.end (), *nameAttr) == fontNames.end ())
|
||||
{
|
||||
std::vector<std::string> alternativeFontNames;
|
||||
attributes->getStringArrayAttribute ("alternative-font-names",
|
||||
alternativeFontNames);
|
||||
for (auto& alternateFontName : alternativeFontNames)
|
||||
{
|
||||
auto trimmedString = trim (UTF8String (alternateFontName));
|
||||
if (std::find (fontNames.begin (), fontNames.end (),
|
||||
trimmedString.getString ()) != fontNames.end ())
|
||||
{
|
||||
font = new CFontDesc (trimmedString.data (), size, fontStyle);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (font == nullptr)
|
||||
font = new CFontDesc (nameAttr->c_str (), size, fontStyle);
|
||||
}
|
||||
}
|
||||
return font;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void UIFontNode::setFont (CFontRef newFont)
|
||||
{
|
||||
if (font)
|
||||
font->forget ();
|
||||
font = newFont;
|
||||
font->remember ();
|
||||
|
||||
std::string name (*attributes->getAttributeValue ("name"));
|
||||
std::string alternativeNames;
|
||||
getAlternativeFontNames (alternativeNames);
|
||||
|
||||
attributes->removeAll ();
|
||||
attributes->setAttribute ("name", name);
|
||||
attributes->setAttribute ("font-name", newFont->getName ().getString ());
|
||||
std::stringstream str;
|
||||
str << newFont->getSize ();
|
||||
attributes->setAttribute ("size", str.str ());
|
||||
if (newFont->getStyle () & kBoldFace)
|
||||
attributes->setAttribute ("bold", "true");
|
||||
if (newFont->getStyle () & kItalicFace)
|
||||
attributes->setAttribute ("italic", "true");
|
||||
if (newFont->getStyle () & kUnderlineFace)
|
||||
attributes->setAttribute ("underline", "true");
|
||||
if (newFont->getStyle () & kStrikethroughFace)
|
||||
attributes->setAttribute ("strike-through", "true");
|
||||
|
||||
setAlternativeFontNames (alternativeNames.c_str ());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void UIFontNode::setAlternativeFontNames (UTF8StringPtr fontNames)
|
||||
{
|
||||
if (fontNames && fontNames[0] != 0)
|
||||
{
|
||||
attributes->setAttribute ("alternative-font-names", fontNames);
|
||||
}
|
||||
else
|
||||
{
|
||||
attributes->removeAttribute ("alternative-font-names");
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool UIFontNode::getAlternativeFontNames (std::string& fontNames)
|
||||
{
|
||||
const std::string* value = attributes->getAttributeValue ("alternative-font-names");
|
||||
if (value)
|
||||
{
|
||||
fontNames = *value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
UIColorNode::UIColorNode (const std::string& name, const SharedPointer<UIAttributes>& attributes)
|
||||
: UINode (name, attributes)
|
||||
{
|
||||
color.alpha = 255;
|
||||
const std::string* red = attributes->getAttributeValue ("red");
|
||||
const std::string* green = attributes->getAttributeValue ("green");
|
||||
const std::string* blue = attributes->getAttributeValue ("blue");
|
||||
const std::string* alpha = attributes->getAttributeValue ("alpha");
|
||||
const std::string* rgb = attributes->getAttributeValue ("rgb");
|
||||
const std::string* rgba = attributes->getAttributeValue ("rgba");
|
||||
if (red)
|
||||
color.red = (uint8_t)strtol (red->c_str (), nullptr, 10);
|
||||
if (green)
|
||||
color.green = (uint8_t)strtol (green->c_str (), nullptr, 10);
|
||||
if (blue)
|
||||
color.blue = (uint8_t)strtol (blue->c_str (), nullptr, 10);
|
||||
if (alpha)
|
||||
color.alpha = (uint8_t)strtol (alpha->c_str (), nullptr, 10);
|
||||
if (rgb)
|
||||
parseColor (*rgb, color);
|
||||
if (rgba)
|
||||
parseColor (*rgba, color);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void UIColorNode::setColor (const CColor& newColor)
|
||||
{
|
||||
std::string name (*attributes->getAttributeValue ("name"));
|
||||
attributes->removeAll ();
|
||||
attributes->setAttribute ("name", name);
|
||||
|
||||
std::string colorString;
|
||||
UIViewCreator::colorToString (newColor, colorString, nullptr);
|
||||
attributes->setAttribute ("rgba", colorString);
|
||||
color = newColor;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
UIGradientNode::UIGradientNode (const std::string& name,
|
||||
const SharedPointer<UIAttributes>& attributes)
|
||||
: UINode (name, attributes)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void UIGradientNode::freePlatformResources ()
|
||||
{
|
||||
gradient = nullptr;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
CGradient* UIGradientNode::getGradient ()
|
||||
{
|
||||
if (gradient == nullptr)
|
||||
{
|
||||
GradientColorStopMap colorStops;
|
||||
double start;
|
||||
CColor color;
|
||||
for (auto& colorNode : getChildren ())
|
||||
{
|
||||
if (colorNode->getName () == "color-stop")
|
||||
{
|
||||
const std::string* rgba = colorNode->getAttributes ()->getAttributeValue ("rgba");
|
||||
if (rgba == nullptr ||
|
||||
colorNode->getAttributes ()->getDoubleAttribute ("start", start) == false)
|
||||
continue;
|
||||
if (parseColor (*rgba, color) == false)
|
||||
continue;
|
||||
colorStops.emplace (start, color);
|
||||
}
|
||||
}
|
||||
if (colorStops.size () > 1)
|
||||
gradient = owned (CGradient::create (colorStops));
|
||||
}
|
||||
return gradient;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void UIGradientNode::setGradient (CGradient* g)
|
||||
{
|
||||
gradient = g;
|
||||
getChildren ().removeAll ();
|
||||
if (gradient == nullptr)
|
||||
return;
|
||||
|
||||
const GradientColorStopMap colorStops = gradient->getColorStops ();
|
||||
for (const auto& colorStop : colorStops)
|
||||
{
|
||||
UINode* node = new UINode ("color-stop");
|
||||
node->getAttributes ()->setDoubleAttribute ("start", colorStop.first);
|
||||
std::string colorString;
|
||||
UIViewCreator::colorToString (colorStop.second, colorString, nullptr);
|
||||
node->getAttributes ()->setAttribute ("rgba", colorString);
|
||||
getChildren ().add (node);
|
||||
}
|
||||
}
|
||||
|
||||
} // Detail
|
||||
} // VSTGUI
|
||||
@@ -0,0 +1,201 @@
|
||||
// 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 "../../lib/vstguifwd.h"
|
||||
#include "../uidescriptionfwd.h"
|
||||
#include "../../lib/ccolor.h"
|
||||
#include "uidesclist.h"
|
||||
|
||||
#include <variant>
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace VSTGUI {
|
||||
namespace Detail {
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace MainNodeNames {
|
||||
|
||||
static constexpr IdStringPtr kBitmap = "bitmaps";
|
||||
static constexpr IdStringPtr kFont = "fonts";
|
||||
static constexpr IdStringPtr kColor = "colors";
|
||||
static constexpr IdStringPtr kControlTag = "control-tags";
|
||||
static constexpr IdStringPtr kVariable = "variables";
|
||||
static constexpr IdStringPtr kTemplate = "template";
|
||||
static constexpr IdStringPtr kCustom = "custom";
|
||||
static constexpr IdStringPtr kGradient = "gradients";
|
||||
|
||||
} // MainNodeNames
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class UINode : public NonAtomicReferenceCounted
|
||||
{
|
||||
public:
|
||||
using DataStorage = std::string;
|
||||
|
||||
UINode (const std::string& name, const SharedPointer<UIAttributes>& attributes = {},
|
||||
bool needsFastChildNameAttributeLookup = false);
|
||||
UINode (const std::string& name, const SharedPointer<UIDescList>& children,
|
||||
const SharedPointer<UIAttributes>& attributes = {});
|
||||
UINode (const UINode& n);
|
||||
~UINode () noexcept override;
|
||||
|
||||
const std::string& getName () const { return name; }
|
||||
DataStorage& getData () { return data; }
|
||||
const DataStorage& getData () const { return data; }
|
||||
|
||||
void setData (DataStorage&& newData);
|
||||
|
||||
const SharedPointer<UIAttributes>& getAttributes () const { return attributes; }
|
||||
UIDescList& getChildren () const { return *children; }
|
||||
bool hasChildren () const;
|
||||
void childAttributeChanged (UINode* child, const char* attributeName,
|
||||
const char* oldAttributeValue);
|
||||
|
||||
enum
|
||||
{
|
||||
kNoExport = 1 << 0
|
||||
};
|
||||
|
||||
bool noExport () const { return hasBit (flags, kNoExport); }
|
||||
void noExport (bool state) { setBit (flags, kNoExport, state); }
|
||||
|
||||
bool operator== (const UINode& n) const { return name == n.name; }
|
||||
|
||||
void sortChildren ();
|
||||
virtual void freePlatformResources () {}
|
||||
|
||||
protected:
|
||||
std::string name;
|
||||
DataStorage data;
|
||||
SharedPointer<UIAttributes> attributes;
|
||||
SharedPointer<UIDescList> children;
|
||||
int32_t flags;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class UICommentNode : public UINode
|
||||
{
|
||||
public:
|
||||
explicit UICommentNode (const std::string& comment);
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class UIVariableNode : public UINode
|
||||
{
|
||||
public:
|
||||
UIVariableNode (const std::string& name, const SharedPointer<UIAttributes>& attributes);
|
||||
|
||||
enum Type
|
||||
{
|
||||
kNumber,
|
||||
kString,
|
||||
kUnknown
|
||||
};
|
||||
|
||||
Type getType () const;
|
||||
double getNumber () const;
|
||||
const std::string& getString () const;
|
||||
|
||||
protected:
|
||||
Type type;
|
||||
double number;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class UIControlTagNode : public UINode
|
||||
{
|
||||
public:
|
||||
UIControlTagNode (const std::string& name, const SharedPointer<UIAttributes>& attributes);
|
||||
int32_t getTag ();
|
||||
void setTag (int32_t newTag);
|
||||
|
||||
const std::string* getTagString () const;
|
||||
void setTagString (const std::string& str);
|
||||
|
||||
protected:
|
||||
int32_t tag;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class UIBitmapNode : public UINode
|
||||
{
|
||||
public:
|
||||
UIBitmapNode (const std::string& name, const SharedPointer<UIAttributes>& attributes);
|
||||
CBitmap* getBitmap (const std::string& pathHint);
|
||||
void setBitmap (UTF8StringPtr bitmapName);
|
||||
void setMultiFrameDesc (const CMultiFrameBitmapDescription* desc);
|
||||
void setNinePartTiledOffset (const CRect* offsets);
|
||||
void invalidBitmap ();
|
||||
bool getFilterProcessed () const { return filterProcessed; }
|
||||
void setFilterProcessed () { filterProcessed = true; }
|
||||
bool getScaledBitmapsAdded () const { return scaledBitmapsAdded; }
|
||||
void setScaledBitmapsAdded () { scaledBitmapsAdded = true; }
|
||||
|
||||
void createXMLData (const std::string& pathHint);
|
||||
void removeXMLData ();
|
||||
bool hasXMLData () const;
|
||||
|
||||
void freePlatformResources () override;
|
||||
|
||||
protected:
|
||||
~UIBitmapNode () noexcept override;
|
||||
using BitmapVariant =
|
||||
std::variant<uint32_t, CNinePartTiledDescription, CMultiFrameBitmapDescription>;
|
||||
CBitmap* createBitmap (const std::string& str, const BitmapVariant& variant) const;
|
||||
PlatformBitmapPtr createBitmapFromDataNode () const;
|
||||
static bool imagesEqual (IPlatformBitmap* b1, IPlatformBitmap* b2);
|
||||
UINode* dataNode () const;
|
||||
CBitmap* bitmap;
|
||||
bool filterProcessed;
|
||||
bool scaledBitmapsAdded;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class UIFontNode : public UINode
|
||||
{
|
||||
public:
|
||||
UIFontNode (const std::string& name, const SharedPointer<UIAttributes>& attributes);
|
||||
CFontRef getFont ();
|
||||
void setFont (CFontRef newFont);
|
||||
void setAlternativeFontNames (UTF8StringPtr fontNames);
|
||||
bool getAlternativeFontNames (std::string& fontNames);
|
||||
|
||||
void freePlatformResources () override;
|
||||
|
||||
protected:
|
||||
~UIFontNode () noexcept override;
|
||||
CFontRef font;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class UIColorNode : public UINode
|
||||
{
|
||||
public:
|
||||
UIColorNode (const std::string& name, const SharedPointer<UIAttributes>& attributes);
|
||||
const CColor& getColor () const { return color; }
|
||||
void setColor (const CColor& newColor);
|
||||
|
||||
protected:
|
||||
CColor color;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class UIGradientNode : public UINode
|
||||
{
|
||||
public:
|
||||
UIGradientNode (const std::string& name, const SharedPointer<UIAttributes>& attributes);
|
||||
CGradient* getGradient ();
|
||||
void setGradient (CGradient* g);
|
||||
|
||||
void freePlatformResources () override;
|
||||
|
||||
protected:
|
||||
SharedPointer<CGradient> gradient;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // Detail
|
||||
} // VSTGUI
|
||||
+344
@@ -0,0 +1,344 @@
|
||||
// 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"
|
||||
#include <cstring>
|
||||
|
||||
namespace VSTGUI {
|
||||
namespace UIViewCreator {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// view names
|
||||
//-----------------------------------------------------------------------------
|
||||
static const IdStringPtr kCView = "CView";
|
||||
static const IdStringPtr kCViewContainer = "CViewContainer";
|
||||
static const IdStringPtr kCLayeredViewContainer = "CLayeredViewContainer";
|
||||
static const IdStringPtr kCRowColumnView = "CRowColumnView";
|
||||
static const IdStringPtr kCScrollView = "CScrollView";
|
||||
static const IdStringPtr kUIViewSwitchContainer = "UIViewSwitchContainer";
|
||||
static const IdStringPtr kCSplitView = "CSplitView";
|
||||
static const IdStringPtr kCShadowViewContainer = "CShadowViewContainer";
|
||||
|
||||
static const IdStringPtr kCControl = "CControl";
|
||||
static const IdStringPtr kCOnOffButton = "COnOffButton";
|
||||
static const IdStringPtr kCCheckBox = "CCheckBox";
|
||||
static const IdStringPtr kCParamDisplay = "CParamDisplay";
|
||||
static const IdStringPtr kCXYPad = "CXYPad";
|
||||
static const IdStringPtr kCOptionMenu = "COptionMenu";
|
||||
static const IdStringPtr kCTextLabel = "CTextLabel";
|
||||
static const IdStringPtr kCMultiLineTextLabel = "CMultiLineTextLabel";
|
||||
static const IdStringPtr kCTextEdit = "CTextEdit";
|
||||
static const IdStringPtr kCSearchTextEdit = "CSearchTextEdit";
|
||||
static const IdStringPtr kCTextButton = "CTextButton";
|
||||
static const IdStringPtr kCSegmentButton = "CSegmentButton";
|
||||
static const IdStringPtr kCKnob = "CKnob";
|
||||
static const IdStringPtr kCAnimKnob = "CAnimKnob";
|
||||
static const IdStringPtr kCVerticalSwitch = "CVerticalSwitch";
|
||||
static const IdStringPtr kCHorizontalSwitch = "CHorizontalSwitch";
|
||||
static const IdStringPtr kCRockerSwitch = "CRockerSwitch";
|
||||
static const IdStringPtr kCMovieBitmap = "CMovieBitmap";
|
||||
static const IdStringPtr kCMovieButton = "CMovieButton";
|
||||
static const IdStringPtr kCKickButton = "CKickButton";
|
||||
static const IdStringPtr kCSlider = "CSlider";
|
||||
static const IdStringPtr kCVuMeter = "CVuMeter";
|
||||
static const IdStringPtr kCAnimationSplashScreen = "CAnimationSplashScreen";
|
||||
static const IdStringPtr kCGradientView = "CGradientView";
|
||||
static const IdStringPtr kCStringListControl = "CStringListControl";
|
||||
static const IdStringPtr kCAutoAnimation = "CAutoAnimation";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// attributes used in more than one view creator
|
||||
//-----------------------------------------------------------------------------
|
||||
static const std::string kAttrClass = "class";
|
||||
static const std::string kAttrTitle = "title";
|
||||
static const std::string kAttrFont = "font";
|
||||
static const std::string kAttrFontColor = "font-color";
|
||||
static const std::string kAttrFrameColor = "frame-color";
|
||||
static const std::string kAttrTextAlignment = "text-alignment";
|
||||
static const std::string kAttrRoundRectRadius = "round-rect-radius";
|
||||
static const std::string kAttrFrameWidth = "frame-width";
|
||||
static const std::string kAttrGradientStartColor = "gradient-start-color";
|
||||
static const std::string kAttrGradientEndColor = "gradient-end-color";
|
||||
static const std::string kAttrZoomFactor = "zoom-factor";
|
||||
static const std::string kAttrHandleBitmap = "handle-bitmap";
|
||||
static const std::string kAttrOrientation = "orientation";
|
||||
static const std::string kAttrAnimationTime = "animation-time";
|
||||
static const std::string kAttrGradient = "gradient";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CViewCreator attributes
|
||||
//-----------------------------------------------------------------------------
|
||||
static const std::string kAttrOrigin = "origin";
|
||||
static const std::string kAttrSize = "size";
|
||||
static const std::string kAttrTransparent = "transparent";
|
||||
static const std::string kAttrMouseEnabled = "mouse-enabled";
|
||||
static const std::string kAttrWantsFocus = "wants-focus";
|
||||
static const std::string kAttrBitmap = "bitmap";
|
||||
static const std::string kAttrDisabledBitmap = "disabled-bitmap";
|
||||
static const std::string kAttrAutosize = "autosize";
|
||||
static const std::string kAttrTooltip = "tooltip";
|
||||
static const std::string kAttrCustomViewName = IUIDescription::kCustomViewName;
|
||||
static const std::string kAttrSubController = "sub-controller";
|
||||
static const std::string kAttrUIDescLabel = "uidesc-label";
|
||||
static const std::string kAttrOpacity = "opacity";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CViewContainerCreator attributes
|
||||
//-----------------------------------------------------------------------------
|
||||
static const std::string kAttrBackgroundColor = "background-color";
|
||||
static const std::string kAttrBackgroundColorDrawStyle = "background-color-draw-style";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CLayeredViewContainerCreator attributes
|
||||
//-----------------------------------------------------------------------------
|
||||
static const std::string kAttrZIndex = "z-index";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CRowColumnViewCreator attributes
|
||||
//-----------------------------------------------------------------------------
|
||||
static const std::string kAttrRowStyle = "row-style";
|
||||
static const std::string kAttrSpacing = "spacing";
|
||||
static const std::string kAttrMargin = "margin";
|
||||
static const std::string kAttrAnimateViewResizing = "animate-view-resizing";
|
||||
static const std::string kAttrHideClippedSubviews = "hide-clipped-subviews";
|
||||
static const std::string kAttrEqualSizeLayout = "equal-size-layout";
|
||||
static const std::string kAttrViewResizeAnimationTime = "view-resize-animation-time";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CScrollViewCreator attributes
|
||||
//-----------------------------------------------------------------------------
|
||||
static const std::string kAttrContainerSize = "container-size";
|
||||
static const std::string kAttrHorizontalScrollbar = "horizontal-scrollbar";
|
||||
static const std::string kAttrVerticalScrollbar = "vertical-scrollbar";
|
||||
static const std::string kAttrAutoDragScrolling = "auto-drag-scrolling";
|
||||
static const std::string kAttrBordered = "bordered";
|
||||
static const std::string kAttrOverlayScrollbars = "overlay-scrollbars";
|
||||
static const std::string kAttrFollowFocusView = "follow-focus-view";
|
||||
static const std::string kAttrAutoHideScrollbars = "auto-hide-scrollbars";
|
||||
static const std::string kAttrScrollbarBackgroundColor = "scrollbar-background-color";
|
||||
static const std::string kAttrScrollbarFrameColor = "scrollbar-frame-color";
|
||||
static const std::string kAttrScrollbarScrollerColor = "scrollbar-scroller-color";
|
||||
static const std::string kAttrScrollbarWidth = "scrollbar-width";
|
||||
static const std::string kAttrMinScrollerSize = "scrollbar-min-scroller-size";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CControlCreator attributes
|
||||
//-----------------------------------------------------------------------------
|
||||
static const std::string kAttrControlTag = "control-tag";
|
||||
static const std::string kAttrDefaultValue = "default-value";
|
||||
static const std::string kAttrMinValue = "min-value";
|
||||
static const std::string kAttrMaxValue = "max-value";
|
||||
static const std::string kAttrWheelIncValue = "wheel-inc-value";
|
||||
static const std::string kAttrBackgroundOffset = "background-offset";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CCheckBoxCreator attributes
|
||||
//-----------------------------------------------------------------------------
|
||||
static const std::string kAttrBoxframeColor = "boxframe-color";
|
||||
static const std::string kAttrBoxfillColor = "boxfill-color";
|
||||
static const std::string kAttrCheckmarkColor = "checkmark-color";
|
||||
static const std::string kAttrDrawCrossbox = "draw-crossbox";
|
||||
static const std::string kAttrAutosizeToFit = "autosize-to-fit";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CParamDisplayCreator attributes
|
||||
//-----------------------------------------------------------------------------
|
||||
static const std::string kAttrBackColor = "back-color";
|
||||
static const std::string kAttrShadowColor = "shadow-color";
|
||||
static const std::string kAttrFontAntialias = "font-antialias";
|
||||
static const std::string kAttrStyle3DIn = "style-3D-in";
|
||||
static const std::string kAttrStyle3DOut = "style-3D-out";
|
||||
static const std::string kAttrStyleNoFrame = "style-no-frame";
|
||||
static const std::string kAttrStyleNoText = "style-no-text";
|
||||
static const std::string kAttrStyleNoDraw = "style-no-draw";
|
||||
static const std::string kAttrStyleShadowText = "style-shadow-text";
|
||||
static const std::string kAttrStyleRoundRect = "style-round-rect";
|
||||
static const std::string kAttrTextInset = "text-inset";
|
||||
static const std::string kAttrValuePrecision = "value-precision";
|
||||
static const std::string kAttrTextRotation = "text-rotation";
|
||||
static const std::string kAttrTextShadowOffset = "text-shadow-offset";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// COptionMenuCreator attributes
|
||||
//-----------------------------------------------------------------------------
|
||||
static const std::string kAttrMenuPopupStyle = "menu-popup-style";
|
||||
static const std::string kAttrMenuCheckStyle = "menu-check-style";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CTextLabelCreator attributes
|
||||
//-----------------------------------------------------------------------------
|
||||
static const std::string kAttrTruncateMode = "truncate-mode";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CMultiLineTextLabelCreator attributes
|
||||
//-----------------------------------------------------------------------------
|
||||
static const std::string kAttrLineLayout = "line-layout";
|
||||
static const std::string kAttrAutoHeight = "auto-height";
|
||||
static const std::string kAttrVerticalCentered = "vertical-centered";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CTextEditCreator attributes
|
||||
//-----------------------------------------------------------------------------
|
||||
static const std::string kAttrSecureStyle = "secure-style";
|
||||
static const std::string kAttrImmediateTextChange = "immediate-text-change";
|
||||
static const std::string kAttrStyleDoubleClick = "style-doubleclick";
|
||||
static const std::string kAttrPlaceholderTitle = "placeholder-title";
|
||||
|
||||
static const std::string kAttrClearMarkInset = "clearmark-inset";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CTextButtonCreator attributes
|
||||
//-----------------------------------------------------------------------------
|
||||
static const std::string kAttrTextColor = "text-color";
|
||||
static const std::string kAttrTextColorHighlighted = "text-color-highlighted";
|
||||
static const std::string kAttrGradientStartColorHighlighted = "gradient-start-color-highlighted";
|
||||
static const std::string kAttrGradientEndColorHighlighted = "gradient-end-color-highlighted";
|
||||
static const std::string kAttrFrameColorHighlighted = "frame-color-highlighted";
|
||||
static const std::string kAttrRoundRadius = "round-radius";
|
||||
static const std::string kAttrKickStyle = "kick-style";
|
||||
static const std::string kAttrIcon = "icon";
|
||||
static const std::string kAttrIconHighlighted = "icon-highlighted";
|
||||
static const std::string kAttrIconPosition = "icon-position";
|
||||
static const std::string kAttrIconTextMargin = "icon-text-margin";
|
||||
static const std::string kAttrGradientHighlighted = "gradient-highlighted";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CSegmentButtonCreator attributes
|
||||
//-----------------------------------------------------------------------------
|
||||
static const std::string kAttrStyle = "style";
|
||||
static const std::string kAttrSelectionMode = "selection-mode";
|
||||
static const std::string kAttrSegmentNames = "segment-names";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CKnobCreator attributes
|
||||
//-----------------------------------------------------------------------------
|
||||
static const std::string kAttrAngleStart = "angle-start";
|
||||
static const std::string kAttrAngleRange = "angle-range";
|
||||
static const std::string kAttrKnobRange = "knob-range";
|
||||
static const std::string kAttrValueInset = "value-inset";
|
||||
static const std::string kAttrCoronaInset = "corona-inset";
|
||||
static const std::string kAttrCoronaColor = "corona-color";
|
||||
static const std::string kAttrCoronaDrawing = "corona-drawing";
|
||||
static const std::string kAttrCoronaOutline = "corona-outline";
|
||||
static const std::string kAttrCoronaInverted = "corona-inverted";
|
||||
static const std::string kAttrCoronaFromCenter = "corona-from-center";
|
||||
static const std::string kAttrCoronaDashDot = "corona-dash-dot";
|
||||
static const std::string kAttrCoronaDashDotLengths = "corona-dash-dot-lengths";
|
||||
static const std::string kAttrHandleColor = "handle-color";
|
||||
static const std::string kAttrHandleShadowColor = "handle-shadow-color";
|
||||
static const std::string kAttrHandleLineWidth = "handle-line-width";
|
||||
static const std::string kAttrCircleDrawing = "circle-drawing";
|
||||
static const std::string kAttrCoronaLineCapButt = "corona-line-cap-butt";
|
||||
static const std::string kAttrSkipHandleDrawing = "skip-handle-drawing";
|
||||
static const std::string kAttrCoronaOutlineWidthAdd = "corona-outline-width-add";
|
||||
|
||||
#if VSTGUI_ENABLE_DEPRECATED_METHODS
|
||||
//-----------------------------------------------------------------------------
|
||||
// IMultiBitmapControlCreator attributes
|
||||
//-----------------------------------------------------------------------------
|
||||
static const std::string kAttrHeightOfOneImage = "height-of-one-image";
|
||||
static const std::string kAttrSubPixmaps = "sub-pixmaps";
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CAnimKnobCreator attributes
|
||||
//-----------------------------------------------------------------------------
|
||||
static const std::string kAttrInverseBitmap = "inverse-bitmap";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CSliderCreator attributes
|
||||
//-----------------------------------------------------------------------------
|
||||
static const std::string kAttrMode = "mode";
|
||||
static const std::string kAttrHandleOffset = "handle-offset";
|
||||
static const std::string kAttrBitmapOffset = "bitmap-offset";
|
||||
static const std::string kAttrReverseOrientation = "reverse-orientation";
|
||||
static const std::string kAttrDrawFrame = "draw-frame";
|
||||
static const std::string kAttrDrawBack = "draw-back";
|
||||
static const std::string kAttrDrawValue = "draw-value";
|
||||
static const std::string kAttrDrawValueInverted = "draw-value-inverted";
|
||||
static const std::string kAttrDrawValueFromCenter = "draw-value-from-center";
|
||||
static const std::string kAttrDrawFrameColor = "draw-frame-color";
|
||||
static const std::string kAttrDrawBackColor = "draw-back-color";
|
||||
static const std::string kAttrDrawValueColor = "draw-value-color";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CVuMeterCreator attributes
|
||||
//-----------------------------------------------------------------------------
|
||||
static const std::string kAttrOffBitmap = "off-bitmap";
|
||||
static const std::string kAttrNumLed = "num-led";
|
||||
static const std::string kAttrDecreaseStepValue = "decrease-step-value";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CAnimationSplashScreenCreator attributes
|
||||
//-----------------------------------------------------------------------------
|
||||
static const std::string kAttrSplashBitmap = "splash-bitmap";
|
||||
static const std::string kAttrSplashOrigin = "splash-origin";
|
||||
static const std::string kAttrSplashSize = "splash-size";
|
||||
static const std::string kAttrAnimationIndex = "animation-index";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// UIViewSwitchContainerCreator attributes
|
||||
//-----------------------------------------------------------------------------
|
||||
static const std::string kAttrTemplateNames = "template-names";
|
||||
static const std::string kAttrTemplateSwitchControl = "template-switch-control";
|
||||
static const std::string kAttrAnimationStyle = "animation-style";
|
||||
static const std::string kAttrAnimationTimingFunction = "animation-timing-function";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CSplitViewCreator attributes
|
||||
//-----------------------------------------------------------------------------
|
||||
static const std::string kAttrSeparatorWidth = "separator-width";
|
||||
static const std::string kAttrResizeMethod = "resize-method";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CShadowViewContainerCreator attributes
|
||||
//-----------------------------------------------------------------------------
|
||||
static const std::string kAttrShadowIntensity = "shadow-intensity";
|
||||
static const std::string kAttrShadowBlurSize = "shadow-blur-size";
|
||||
static const std::string kAttrShadowOffset = "shadow-offset";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CGradientViewCreator attributes
|
||||
//-----------------------------------------------------------------------------
|
||||
static const std::string kAttrGradientAngle = "gradient-angle";
|
||||
static const std::string kAttrGradientStyle = "gradient-style";
|
||||
static const std::string kAttrGradientStartColorOffset = "gradient-start-color-offset";
|
||||
static const std::string kAttrGradientEndColorOffset = "gradient-end-color-offset";
|
||||
static const std::string kAttrDrawAntialiased = "draw-antialiased";
|
||||
static const std::string kAttrRadialCenter = "radial-center";
|
||||
static const std::string kAttrRadialRadius = "radial-radius";
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// StringListControlCreator attributes
|
||||
//------------------------------------------------------------------------
|
||||
static const std::string kAttrSelectedFontColor = "font-color-selected";
|
||||
static const std::string kAttrSelectedBackColor = "back-color-selected";
|
||||
static const std::string kAttrLineColor = "line-color";
|
||||
static const std::string kAttrLineWidth = "line-width";
|
||||
static const std::string kAttrHoverColor = "hover-color";
|
||||
static const std::string kAttrRowHeight = "row-height";
|
||||
static const std::string kAttrStyleHover = "style-hover";
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Some globally used strings
|
||||
//------------------------------------------------------------------------
|
||||
static constexpr auto strTrue = "true";
|
||||
static constexpr auto strFalse = "false";
|
||||
static constexpr auto strHorizontal = "horizontal";
|
||||
static constexpr auto strVertical = "vertical";
|
||||
static constexpr auto strHorizontalInverse = "horizontal-inverse";
|
||||
static constexpr auto strVerticalInverse = "vertical-inverse";
|
||||
|
||||
static constexpr auto strNone = "none";
|
||||
static constexpr auto strHead = "head";
|
||||
static constexpr auto strTail = "tail";
|
||||
|
||||
static constexpr auto strLeft = "left";
|
||||
static constexpr auto strRight = "right";
|
||||
static constexpr auto strCenter = "center";
|
||||
|
||||
} // UIViewCreator
|
||||
} // VSTGUI
|
||||
+315
@@ -0,0 +1,315 @@
|
||||
// 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 "uixmlpersistence.h"
|
||||
|
||||
#if VSTGUI_ENABLE_XML_PARSER
|
||||
|
||||
#include "../uiattributes.h"
|
||||
#include "../cstream.h"
|
||||
#include <map>
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace VSTGUI {
|
||||
namespace Detail {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
SharedPointer<UINode> UIXMLParser::parse (IContentProvider* provider)
|
||||
{
|
||||
Xml::Parser parser;
|
||||
if (parser.parse (provider, this))
|
||||
return std::move (nodes);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void UIXMLParser::startXmlElement (Xml::Parser* parser, IdStringPtr elementName, UTF8StringPtr* elementAttributes)
|
||||
{
|
||||
std::string name (elementName);
|
||||
if (nodes)
|
||||
{
|
||||
UINode* parent = nodeStack.back ();
|
||||
UINode* newNode = nullptr;
|
||||
if (restoreViewsMode)
|
||||
{
|
||||
if (name != "view" && name != MainNodeNames::kCustom)
|
||||
{
|
||||
parser->stop ();
|
||||
}
|
||||
newNode = new UINode (name, makeOwned<UIAttributes> (elementAttributes));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (parent == nodes)
|
||||
{
|
||||
// only allowed second level elements
|
||||
if (name == MainNodeNames::kControlTag || name == MainNodeNames::kColor || name == MainNodeNames::kBitmap)
|
||||
newNode = new UINode (name, makeOwned<UIAttributes> (elementAttributes), true);
|
||||
else if (name == MainNodeNames::kFont || name == MainNodeNames::kTemplate
|
||||
|| name == MainNodeNames::kControlTag || name == MainNodeNames::kCustom
|
||||
|| name == MainNodeNames::kVariable || name == MainNodeNames::kGradient)
|
||||
newNode = new UINode (name, makeOwned<UIAttributes> (elementAttributes));
|
||||
else
|
||||
parser->stop ();
|
||||
}
|
||||
else if (parent->getName () == MainNodeNames::kBitmap)
|
||||
{
|
||||
if (name == "bitmap")
|
||||
newNode = new UIBitmapNode (name, makeOwned<UIAttributes> (elementAttributes));
|
||||
else
|
||||
parser->stop ();
|
||||
}
|
||||
else if (parent->getName () == MainNodeNames::kFont)
|
||||
{
|
||||
if (name == "font")
|
||||
newNode = new UIFontNode (name, makeOwned<UIAttributes> (elementAttributes));
|
||||
else
|
||||
parser->stop ();
|
||||
}
|
||||
else if (parent->getName () == MainNodeNames::kColor)
|
||||
{
|
||||
if (name == "color")
|
||||
newNode = new UIColorNode (name, makeOwned<UIAttributes> (elementAttributes));
|
||||
else
|
||||
parser->stop ();
|
||||
}
|
||||
else if (parent->getName () == MainNodeNames::kControlTag)
|
||||
{
|
||||
if (name == "control-tag")
|
||||
newNode = new UIControlTagNode (name, makeOwned<UIAttributes> (elementAttributes));
|
||||
else
|
||||
parser->stop ();
|
||||
}
|
||||
else if (parent->getName () == MainNodeNames::kVariable)
|
||||
{
|
||||
if (name == "var")
|
||||
newNode = new UIVariableNode (name, makeOwned<UIAttributes> (elementAttributes));
|
||||
else
|
||||
parser->stop ();
|
||||
}
|
||||
else if (parent->getName () == MainNodeNames::kGradient)
|
||||
{
|
||||
if (name == "gradient")
|
||||
newNode = new UIGradientNode (name, makeOwned<UIAttributes> (elementAttributes));
|
||||
else
|
||||
parser->stop ();
|
||||
}
|
||||
else
|
||||
newNode = new UINode (name, makeOwned<UIAttributes> (elementAttributes));
|
||||
}
|
||||
if (newNode)
|
||||
{
|
||||
parent->getChildren ().add (newNode);
|
||||
nodeStack.emplace_back (newNode);
|
||||
}
|
||||
}
|
||||
else if (name == "vstgui-ui-description")
|
||||
{
|
||||
nodes = makeOwned<UINode> (name, makeOwned<UIAttributes> (elementAttributes));
|
||||
nodeStack.emplace_back (nodes);
|
||||
}
|
||||
else if (name == "vstgui-ui-description-view-list")
|
||||
{
|
||||
vstgui_assert (nodes == nullptr);
|
||||
nodes = makeOwned<UINode> (name, makeOwned<UIAttributes> (elementAttributes));
|
||||
nodeStack.emplace_back (nodes);
|
||||
restoreViewsMode = true;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void UIXMLParser::endXmlElement (Xml::Parser* parser, IdStringPtr name)
|
||||
{
|
||||
if (nodeStack.back () == nodes)
|
||||
restoreViewsMode = false;
|
||||
nodeStack.pop_back ();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void UIXMLParser::xmlCharData (Xml::Parser* parser, const int8_t* data, int32_t length)
|
||||
{
|
||||
if (nodeStack.empty ())
|
||||
return;
|
||||
auto& nodeData = nodeStack.back ()->getData ();
|
||||
const int8_t* dataStart = nullptr;
|
||||
uint32_t validChars = 0;
|
||||
for (int32_t i = 0; i < length; i++, ++data)
|
||||
{
|
||||
if (*data < 0x21)
|
||||
{
|
||||
if (dataStart)
|
||||
{
|
||||
nodeData.append (reinterpret_cast<const char*> (dataStart), validChars);
|
||||
dataStart = nullptr;
|
||||
validChars = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (dataStart == nullptr)
|
||||
dataStart = data;
|
||||
++validChars;
|
||||
}
|
||||
if (dataStart && validChars > 0)
|
||||
nodeData.append (reinterpret_cast<const char*> (dataStart), validChars);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void UIXMLParser::xmlComment (Xml::Parser* parser, IdStringPtr comment)
|
||||
{
|
||||
#if VSTGUI_LIVE_EDITING
|
||||
if (nodeStack.empty ())
|
||||
{
|
||||
#if DEBUG
|
||||
DebugPrint ("*** WARNING : Comment outside of root tag will be removed on save !\nComment: %s\n", comment);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
UINode* parent = nodeStack.back ();
|
||||
if (parent && comment)
|
||||
{
|
||||
std::string commentStr (comment);
|
||||
if (!commentStr.empty ())
|
||||
{
|
||||
UICommentNode* commentNode = new UICommentNode (comment);
|
||||
parent->getChildren ().add (commentNode);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool UIXMLDescWriter::write (OutputStream& stream, UINode* rootNode)
|
||||
{
|
||||
intendLevel = 0;
|
||||
stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
|
||||
return writeNode (rootNode, stream);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void UIXMLDescWriter::encodeAttributeString (std::string& str)
|
||||
{
|
||||
const int8_t entities[] = {'&', '<','>', '\'', '\"', 0};
|
||||
const char* replacements[] = {"&", "<", ">", "'", """};
|
||||
int32_t i = 0;
|
||||
while (entities[i] != 0)
|
||||
{
|
||||
size_t pos = 0;
|
||||
while ((pos = str.find (entities[i], pos)) != std::string::npos)
|
||||
{
|
||||
str.replace (pos, 1, replacements[i]);
|
||||
pos++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool UIXMLDescWriter::writeAttributes (UIAttributes* attr, OutputStream& stream)
|
||||
{
|
||||
bool result = true;
|
||||
using SortedAttributes = std::map<std::string,std::string>;
|
||||
SortedAttributes sortedAttributes (attr->begin (), attr->end ());
|
||||
for (auto& sa : sortedAttributes)
|
||||
{
|
||||
if (sa.second.length () > 0)
|
||||
{
|
||||
stream << " ";
|
||||
stream << sa.first;
|
||||
stream << "=\"";
|
||||
std::string value (sa.second);
|
||||
encodeAttributeString (value);
|
||||
stream << value;
|
||||
stream << "\"";
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool UIXMLDescWriter::writeNodeData (UINode::DataStorage& str, OutputStream& stream)
|
||||
{
|
||||
for (int32_t i = 0; i < intendLevel; i++) stream << "\t";
|
||||
uint32_t i = 0;
|
||||
for (auto c : str)
|
||||
{
|
||||
stream << static_cast<int8_t> (c);
|
||||
if (i++ > 80)
|
||||
{
|
||||
stream << "\n";
|
||||
i = 0;
|
||||
for (int32_t i2 = 0; i2 < intendLevel; i2++) stream << "\t";
|
||||
}
|
||||
}
|
||||
stream << "\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool UIXMLDescWriter::writeComment (UICommentNode* node, OutputStream& stream)
|
||||
{
|
||||
stream << "<!--";
|
||||
stream << node->getData ();
|
||||
stream << "-->\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool UIXMLDescWriter::writeNode (UINode* node, OutputStream& stream)
|
||||
{
|
||||
if (!node)
|
||||
return false;
|
||||
|
||||
bool result = true;
|
||||
if (node->noExport ())
|
||||
return result;
|
||||
for (int32_t i = 0; i < intendLevel; i++) stream << "\t";
|
||||
if (auto* commentNode = dynamic_cast<UICommentNode*> (node))
|
||||
{
|
||||
return writeComment (commentNode, stream);
|
||||
}
|
||||
stream << "<";
|
||||
stream << node->getName ();
|
||||
result = writeAttributes (node->getAttributes (), stream);
|
||||
if (result)
|
||||
{
|
||||
UIDescList& children = node->getChildren ();
|
||||
if (!children.empty ())
|
||||
{
|
||||
stream << ">\n";
|
||||
intendLevel++;
|
||||
if (!node->getData ().empty ())
|
||||
result = writeNodeData (node->getData (), stream);
|
||||
for (auto& childNode : children)
|
||||
{
|
||||
if (!writeNode (childNode, stream))
|
||||
return false;
|
||||
}
|
||||
intendLevel--;
|
||||
for (int32_t i = 0; i < intendLevel; i++) stream << "\t";
|
||||
stream << "</";
|
||||
stream << node->getName ();
|
||||
stream << ">\n";
|
||||
}
|
||||
else if (!node->getData ().empty ())
|
||||
{
|
||||
stream << ">\n";
|
||||
intendLevel++;
|
||||
result = writeNodeData (node->getData (), stream);
|
||||
intendLevel--;
|
||||
for (int32_t i = 0; i < intendLevel; i++) stream << "\t";
|
||||
stream << "</";
|
||||
stream << node->getName ();
|
||||
stream << ">\n";
|
||||
}
|
||||
else
|
||||
stream << "/>\n";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // Detail
|
||||
} // VSTGUI
|
||||
|
||||
#endif // VSTGUI_ENABLE_XML_PARSER
|
||||
@@ -0,0 +1,60 @@
|
||||
// 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 "../../lib/vstguibase.h"
|
||||
|
||||
#if VSTGUI_ENABLE_XML_PARSER
|
||||
|
||||
#include "uinode.h"
|
||||
#include "../xmlparser.h"
|
||||
#include <deque>
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace VSTGUI {
|
||||
namespace Detail {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
struct UIXMLParser : public Xml::IHandler
|
||||
{
|
||||
SharedPointer<UINode> parse (IContentProvider* provider);
|
||||
|
||||
void startXmlElement (Xml::Parser* parser, IdStringPtr elementName, UTF8StringPtr* elementAttributes) override;
|
||||
void endXmlElement (Xml::Parser* parser, IdStringPtr name) override;
|
||||
void xmlCharData (Xml::Parser* parser, const int8_t* data, int32_t length) override;
|
||||
void xmlComment (Xml::Parser* parser, IdStringPtr comment) override;
|
||||
|
||||
const SharedPointer<UINode> getNodes () const { return nodes; }
|
||||
|
||||
private:
|
||||
SharedPointer<UINode> nodes;
|
||||
std::deque<UINode*> nodeStack;
|
||||
bool restoreViewsMode {false};
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class UIXMLDescWriter
|
||||
{
|
||||
public:
|
||||
using UINode = Detail::UINode;
|
||||
using UICommentNode = Detail::UICommentNode;
|
||||
bool write (OutputStream& stream, UINode* rootNode);
|
||||
protected:
|
||||
static void encodeAttributeString (std::string& str);
|
||||
|
||||
bool writeNode (UINode* node, OutputStream& stream);
|
||||
bool writeComment (UICommentNode* node, OutputStream& stream);
|
||||
bool writeNodeData (UINode::DataStorage& str, OutputStream& stream);
|
||||
bool writeAttributes (UIAttributes* attr, OutputStream& stream);
|
||||
int32_t intendLevel;
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // Detail
|
||||
} // VSTGUI
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user