Initial release
@@ -0,0 +1,232 @@
|
||||
##########################################################################################
|
||||
# VSTGUI UIDescription Library
|
||||
##########################################################################################
|
||||
set(target vstgui_uidescription)
|
||||
|
||||
set(${target}_sources
|
||||
base64codec.h
|
||||
compresseduidescription.cpp
|
||||
compresseduidescription.h
|
||||
cstream.cpp
|
||||
cstream.h
|
||||
cstream_zlib.cpp
|
||||
cstream_zlib.h
|
||||
delegationcontroller.h
|
||||
doc.h
|
||||
icontentprovider.h
|
||||
icontroller.h
|
||||
iuidescription.h
|
||||
iuidescriptionaddon.h
|
||||
iviewcreator.h
|
||||
iviewfactory.h
|
||||
uiattributes.cpp
|
||||
uiattributes.h
|
||||
uicontentprovider.cpp
|
||||
uicontentprovider.h
|
||||
uidescription.cpp
|
||||
uidescription.h
|
||||
uidescriptionaddonregistry.cpp
|
||||
uidescriptionaddonregistry.h
|
||||
uidescriptionlistener.h
|
||||
uidescriptionfwd.h
|
||||
uiviewcreator.cpp
|
||||
uiviewcreator.h
|
||||
uiviewfactory.cpp
|
||||
uiviewfactory.h
|
||||
uiviewswitchcontainer.cpp
|
||||
uiviewswitchcontainer.h
|
||||
xmlparser.cpp
|
||||
xmlparser.h
|
||||
detail/locale.h
|
||||
detail/parsecolor.h
|
||||
detail/scalefactorutils.h
|
||||
detail/uidesclist.cpp
|
||||
detail/uidesclist.h
|
||||
detail/uijsonpersistence.cpp
|
||||
detail/uijsonpersistence.h
|
||||
detail/uinode.cpp
|
||||
detail/uinode.h
|
||||
detail/uiviewcreatorattributes.h
|
||||
detail/uixmlpersistence.cpp
|
||||
detail/uixmlpersistence.h
|
||||
editing/doc.h
|
||||
editing/iaction.h
|
||||
editing/igridprocessor.h
|
||||
editing/uiactions.cpp
|
||||
editing/uiactions.h
|
||||
editing/uiattributescontroller.cpp
|
||||
editing/uiattributescontroller.h
|
||||
editing/uibasedatasource.h
|
||||
editing/uibitmapscontroller.cpp
|
||||
editing/uibitmapscontroller.h
|
||||
editing/uicolor.cpp
|
||||
editing/uicolor.h
|
||||
editing/uicolorchoosercontroller.cpp
|
||||
editing/uicolorchoosercontroller.h
|
||||
editing/uicolorscontroller.cpp
|
||||
editing/uicolorscontroller.h
|
||||
editing/uicolorslider.cpp
|
||||
editing/uicolorslider.h
|
||||
editing/uicrosslines.cpp
|
||||
editing/uicrosslines.h
|
||||
editing/uidescriptioneditor.uidesc
|
||||
editing/uidialogcontroller.cpp
|
||||
editing/uidialogcontroller.h
|
||||
editing/uieditcontroller.cpp
|
||||
editing/uieditcontroller.h
|
||||
editing/uieditmenucontroller.cpp
|
||||
editing/uieditmenucontroller.h
|
||||
editing/uieditview.cpp
|
||||
editing/uieditview.h
|
||||
editing/uifocussettingscontroller.cpp
|
||||
editing/uifocussettingscontroller.h
|
||||
editing/uifontscontroller.cpp
|
||||
editing/uifontscontroller.h
|
||||
editing/uigradientscontroller.cpp
|
||||
editing/uigradientscontroller.h
|
||||
editing/uigrid.h
|
||||
editing/uigridcontroller.cpp
|
||||
editing/uigridcontroller.h
|
||||
editing/uioverlayview.cpp
|
||||
editing/uioverlayview.h
|
||||
editing/uiselection.cpp
|
||||
editing/uiselection.h
|
||||
editing/uitagscontroller.cpp
|
||||
editing/uitagscontroller.h
|
||||
editing/uitemplatecontroller.cpp
|
||||
editing/uitemplatecontroller.h
|
||||
editing/uitemplatesettingscontroller.cpp
|
||||
editing/uitemplatesettingscontroller.h
|
||||
editing/uiundomanager.cpp
|
||||
editing/uiundomanager.h
|
||||
editing/uiviewcreatecontroller.cpp
|
||||
editing/uiviewcreatecontroller.h
|
||||
viewcreator/animationsplashscreencreator.cpp
|
||||
viewcreator/animationsplashscreencreator.h
|
||||
viewcreator/animknobcreator.cpp
|
||||
viewcreator/animknobcreator.h
|
||||
viewcreator/autoanimationcreator.cpp
|
||||
viewcreator/autoanimationcreator.h
|
||||
viewcreator/checkboxcreator.cpp
|
||||
viewcreator/checkboxcreator.h
|
||||
viewcreator/controlcreator.cpp
|
||||
viewcreator/controlcreator.h
|
||||
viewcreator/gradientviewcreator.cpp
|
||||
viewcreator/gradientviewcreator.h
|
||||
viewcreator/kickbuttoncreator.cpp
|
||||
viewcreator/kickbuttoncreator.h
|
||||
viewcreator/knobcreator.cpp
|
||||
viewcreator/knobcreator.h
|
||||
viewcreator/layeredviewcontainercreator.cpp
|
||||
viewcreator/layeredviewcontainercreator.h
|
||||
viewcreator/moviebitmapcreator.cpp
|
||||
viewcreator/moviebitmapcreator.h
|
||||
viewcreator/moviebuttoncreator.cpp
|
||||
viewcreator/moviebuttoncreator.h
|
||||
viewcreator/multibitmapcontrolcreator.cpp
|
||||
viewcreator/multibitmapcontrolcreator.h
|
||||
viewcreator/multilinetextlabelcreator.cpp
|
||||
viewcreator/multilinetextlabelcreator.h
|
||||
viewcreator/onoffbuttoncreator.cpp
|
||||
viewcreator/onoffbuttoncreator.h
|
||||
viewcreator/optionmenucreator.cpp
|
||||
viewcreator/optionmenucreator.h
|
||||
viewcreator/paramdisplaycreator.cpp
|
||||
viewcreator/paramdisplaycreator.h
|
||||
viewcreator/rockerswitchcreator.cpp
|
||||
viewcreator/rockerswitchcreator.h
|
||||
viewcreator/rowcolumnviewcreator.cpp
|
||||
viewcreator/rowcolumnviewcreator.h
|
||||
viewcreator/scrollviewcreator.cpp
|
||||
viewcreator/scrollviewcreator.h
|
||||
viewcreator/searchtexteditcreator.cpp
|
||||
viewcreator/searchtexteditcreator.h
|
||||
viewcreator/segmentbuttoncreator.cpp
|
||||
viewcreator/segmentbuttoncreator.h
|
||||
viewcreator/shadowviewcontainercreator.cpp
|
||||
viewcreator/shadowviewcontainercreator.h
|
||||
viewcreator/sliderviewcreator.cpp
|
||||
viewcreator/sliderviewcreator.h
|
||||
viewcreator/splitviewcreator.cpp
|
||||
viewcreator/splitviewcreator.h
|
||||
viewcreator/stringlistcontrolcreator.cpp
|
||||
viewcreator/stringlistcontrolcreator.h
|
||||
viewcreator/switchcreators.cpp
|
||||
viewcreator/switchcreators.h
|
||||
viewcreator/textbuttoncreator.cpp
|
||||
viewcreator/textbuttoncreator.h
|
||||
viewcreator/texteditcreator.cpp
|
||||
viewcreator/texteditcreator.h
|
||||
viewcreator/textlabelcreator.cpp
|
||||
viewcreator/textlabelcreator.h
|
||||
viewcreator/uiviewswitchcontainercreator.cpp
|
||||
viewcreator/uiviewswitchcontainercreator.h
|
||||
viewcreator/viewcontainercreator.cpp
|
||||
viewcreator/viewcontainercreator.h
|
||||
viewcreator/viewcreator.cpp
|
||||
viewcreator/viewcreator.h
|
||||
viewcreator/vumetercreator.cpp
|
||||
viewcreator/vumetercreator.h
|
||||
viewcreator/xypadcreator.cpp
|
||||
viewcreator/xypadcreator.h
|
||||
)
|
||||
|
||||
##########################################################################################
|
||||
if(CMAKE_HOST_APPLE)
|
||||
set_source_files_properties(detail/uijsonpersistence.cpp PROPERTIES COMPILE_FLAGS -fno-fast-math)
|
||||
endif()
|
||||
|
||||
##########################################################################################
|
||||
if(MSVC)
|
||||
endif()
|
||||
|
||||
##########################################################################################
|
||||
add_library(${target} STATIC ${${target}_sources})
|
||||
|
||||
add_dependencies(${target} vstgui)
|
||||
target_precompile_headers(${target} PRIVATE icontroller.h uiattributes.h iviewcreator.h uidescription.h)
|
||||
target_compile_definitions(${target} ${VSTGUI_COMPILE_DEFINITIONS})
|
||||
vstgui_set_cxx_version(${target} ${VSTGUI_CXX_VERSION})
|
||||
vstgui_source_group_by_folder(${target})
|
||||
|
||||
##########################################################################################
|
||||
if(LINUX)
|
||||
set (VSTGUI_GENERATED_DIR ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.generated)
|
||||
|
||||
execute_process(
|
||||
COMMAND
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/editing/createuidescdata.sh ${VSTGUI_GENERATED_DIR}
|
||||
WORKING_DIRECTORY
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/editing/
|
||||
RESULT_VARIABLE
|
||||
result
|
||||
)
|
||||
|
||||
if(result EQUAL 0)
|
||||
target_compile_definitions(${target} ${VSTGUI_COMPILE_DEFINITIONS} "HAVE_EDITORUIDESC_H")
|
||||
else()
|
||||
message(FATAL_ERROR "Generating editoruidesc.h failed: ${result}")
|
||||
endif()
|
||||
|
||||
target_include_directories(${target}
|
||||
PRIVATE
|
||||
${VSTGUI_GENERATED_DIR}
|
||||
)
|
||||
target_link_libraries(${target} PRIVATE vstgui)
|
||||
endif()
|
||||
##########################################################################################
|
||||
find_package(EXPAT)
|
||||
if(EXPAT_FOUND)
|
||||
target_compile_definitions(${target} ${VSTGUI_COMPILE_DEFINITIONS} "VSTGUI_USE_SYSTEM_EXPAT")
|
||||
target_link_libraries(${target} PRIVATE ${EXPAT_LIBRARY})
|
||||
target_include_directories(${target} PRIVATE ${EXPAT_INCLUDE_DIRS})
|
||||
message(STATUS "VSTGUI will use the Expat library at ${EXPAT_LIBRARY}")
|
||||
message(STATUS "VSTGUI will use the Expat header found in ${EXPAT_INCLUDE_DIRS}")
|
||||
else()
|
||||
message(STATUS "VSTGUI will use the embedded Expat package!")
|
||||
endif()
|
||||
|
||||
if(CMAKE_HOST_APPLE)
|
||||
target_compile_options(${target} PRIVATE -Wall -Werror)
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
// 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/malloc.h"
|
||||
|
||||
namespace VSTGUI {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class Base64Codec
|
||||
{
|
||||
public:
|
||||
struct Result
|
||||
{
|
||||
Buffer<uint8_t> data;
|
||||
uint32_t dataSize {0};
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
static inline Result decode (const T& base64String)
|
||||
{
|
||||
return decode (base64String.data (), base64String.size ());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline Result decode (const T* inBuffer, size_t inBufferSize)
|
||||
{
|
||||
static_assert (sizeof (T) == 1, "T must be one byte type");
|
||||
Result r;
|
||||
r.data.allocate ((inBufferSize * 3 / 4) + 3);
|
||||
uint8_t input1[4];
|
||||
uint8_t input2[4];
|
||||
auto input1Ptr = reinterpret_cast<uint32_t*>(&input1[0]);
|
||||
auto input2Ptr = reinterpret_cast<uint32_t*>(&input2[0]);
|
||||
auto buffer32Ptr = reinterpret_cast<const uint32_t*> (inBuffer);
|
||||
while (inBufferSize > 8)
|
||||
{
|
||||
*input1Ptr = *buffer32Ptr++;
|
||||
*input2Ptr = *buffer32Ptr++;
|
||||
r.dataSize += decodeblock<false> (input1, r.data.get () + r.dataSize);
|
||||
r.dataSize += decodeblock<false> (input2, r.data.get () + r.dataSize);
|
||||
inBufferSize -= 8;
|
||||
}
|
||||
while (inBufferSize > 4)
|
||||
{
|
||||
*input1Ptr = *buffer32Ptr++;
|
||||
r.dataSize += decodeblock<false> (input1, r.data.get () + r.dataSize);
|
||||
inBufferSize -= 4;
|
||||
}
|
||||
if (inBufferSize > 0)
|
||||
{
|
||||
input1[0] = input1[1] = input1[2] = input1[3] = '=';
|
||||
auto ptr = reinterpret_cast<const uint8_t*>(buffer32Ptr);
|
||||
for (uint32_t j = 0; j < inBufferSize; j++)
|
||||
{
|
||||
input1[j] = *ptr++;
|
||||
}
|
||||
r.dataSize += decodeblock<true> (input1, r.data.get () + r.dataSize);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline Result encode (const void* binaryData, size_t binaryDataSize)
|
||||
{
|
||||
Result r;
|
||||
r.data.allocate ((binaryDataSize * 4) / 3 + 4);
|
||||
auto ptr = reinterpret_cast<const uint8_t*> (binaryData);
|
||||
uint8_t input[3];
|
||||
uint32_t i;
|
||||
for (i = 0; i < (binaryDataSize - 3); i += 3)
|
||||
{
|
||||
input[0] = *ptr++;
|
||||
input[1] = *ptr++;
|
||||
input[2] = *ptr++;
|
||||
encodeblock (input, r.data.get () + r.dataSize, 3);
|
||||
r.dataSize += 4;
|
||||
}
|
||||
if (i < binaryDataSize)
|
||||
{
|
||||
input[0] = input[1] = input[2] = 0;
|
||||
uint32_t j;
|
||||
for (j = 0; i < binaryDataSize; i++, j++)
|
||||
{
|
||||
input[j] = *ptr++;
|
||||
}
|
||||
encodeblock (input, r.data.get () + r.dataSize, j);
|
||||
r.dataSize += 4;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
private:
|
||||
template<bool finalBlock = true>
|
||||
static inline uint32_t decodeblock (uint8_t input[4], uint8_t output[3])
|
||||
{
|
||||
static constexpr uint8_t cd64[] = {
|
||||
62, 0xFF, 0xFF, 0xFF, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0xFF,
|
||||
0xFF, 0xFF, 0, 0xFF, 0xFF, 0xFF, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
|
||||
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
|
||||
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51};
|
||||
|
||||
uint32_t result = 3;
|
||||
if (finalBlock)
|
||||
{
|
||||
if (input[2] == '=')
|
||||
result = 1;
|
||||
else if (input[3] == '=')
|
||||
result = 2;
|
||||
}
|
||||
input[0] = cd64[input[0] - 43];
|
||||
input[1] = cd64[input[1] - 43];
|
||||
input[2] = cd64[input[2] - 43];
|
||||
input[3] = cd64[input[3] - 43];
|
||||
output[0] = static_cast<uint8_t> ((input[0] << 2) | ((input[1] & 0x30) >> 4));
|
||||
output[1] = static_cast<uint8_t> (((input[1] & 0xF) << 4) | ((input[2] & 0x3C) >> 2));
|
||||
output[2] = static_cast<uint8_t> (((input[2] & 0x03) << 6) | input[3]);
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline void encodeblock (uint8_t input[3], uint8_t output[4], uint32_t len)
|
||||
{
|
||||
static constexpr uint8_t cb64[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
output[0] = cb64[input[0] >> 2];
|
||||
output[1] = cb64[((input[0] & 0x03) << 4) | ((input[1] & 0xf0) >> 4)];
|
||||
output[2] = static_cast<uint8_t>
|
||||
(len > 1 ? cb64[((input[1] & 0x0f) << 2) | ((input[2] & 0xc0) >> 6)] : '=');
|
||||
output[3] = static_cast<uint8_t>(len > 2 ? cb64[input[2] & 0x3f] : '=');
|
||||
}
|
||||
};
|
||||
|
||||
} // VSTGUI
|
||||
@@ -0,0 +1,156 @@
|
||||
// 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/cresourcedescription.h"
|
||||
#include "compresseduidescription.h"
|
||||
#include "cstream_zlib.h"
|
||||
#include "uicontentprovider.h"
|
||||
#include <array>
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace VSTGUI {
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
class ZLibInputContentProvider : public IContentProvider
|
||||
{
|
||||
public:
|
||||
ZLibInputContentProvider (InputStream& source) : source (source)
|
||||
{
|
||||
if (auto seekStream = dynamic_cast<SeekableStream*>(&source))
|
||||
startPos = seekStream->tell ();
|
||||
}
|
||||
|
||||
bool open ()
|
||||
{
|
||||
zin = std::make_unique<ZLibInputStream>();
|
||||
return zin->open (source);
|
||||
}
|
||||
|
||||
uint32_t readRawData (int8_t* buffer, uint32_t size) override
|
||||
{
|
||||
if (zin)
|
||||
return zin->readRaw (buffer, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rewind () override
|
||||
{
|
||||
if (auto seekStream = dynamic_cast<SeekableStream*>(&source))
|
||||
{
|
||||
seekStream->seek (startPos, SeekableStream::SeekMode::kSeekSet);
|
||||
open ();
|
||||
}
|
||||
}
|
||||
|
||||
InputStream& source;
|
||||
std::unique_ptr<ZLibInputStream> zin;
|
||||
int64_t startPos {0};
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static constexpr int64_t kUIDescIdentifier = 0x7072637365646975LL; // 8 byte identifier
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
CompressedUIDescription::CompressedUIDescription (const CResourceDescription& compressedUIDescFile)
|
||||
: UIDescription (compressedUIDescFile)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CompressedUIDescription::parseWithStream (InputStream& stream)
|
||||
{
|
||||
bool result = false;
|
||||
int64_t identifier;
|
||||
stream >> identifier;
|
||||
if (identifier == kUIDescIdentifier)
|
||||
{
|
||||
ZLibInputContentProvider zin (stream);
|
||||
if (zin.open ())
|
||||
{
|
||||
setContentProvider (&zin);
|
||||
result = UIDescription::parse ();
|
||||
setContentProvider (nullptr);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CompressedUIDescription::parse ()
|
||||
{
|
||||
if (parsed ())
|
||||
return true;
|
||||
bool result = false;
|
||||
CResourceInputStream resStream (kLittleEndianByteOrder);
|
||||
if (resStream.open (getUIDescFile ()))
|
||||
{
|
||||
result = parseWithStream (resStream);
|
||||
}
|
||||
else if (getUIDescFile ().type == CResourceDescription::kStringType)
|
||||
{
|
||||
CFileStream fileStream;
|
||||
if (fileStream.open (getUIDescFile ().u.name,
|
||||
CFileStream::kReadMode | CFileStream::kBinaryMode,
|
||||
kLittleEndianByteOrder))
|
||||
{
|
||||
result = parseWithStream (fileStream);
|
||||
}
|
||||
}
|
||||
if (!result)
|
||||
{
|
||||
// fallback, check if it is an uncompressed UIDescription file
|
||||
return UIDescription::parse ();
|
||||
}
|
||||
originalIsCompressed = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CompressedUIDescription::save (UTF8StringPtr filename, int32_t flags,
|
||||
AttributeSaveFilterFunc func)
|
||||
{
|
||||
bool result = false;
|
||||
if (originalIsCompressed || (flags & kForceWriteCompressedDesc))
|
||||
{
|
||||
CFileStream fileStream;
|
||||
if (fileStream.open (filename,
|
||||
CFileStream::kWriteMode | CFileStream::kBinaryMode |
|
||||
CFileStream::kTruncateMode,
|
||||
kLittleEndianByteOrder))
|
||||
{
|
||||
fileStream << kUIDescIdentifier;
|
||||
ZLibOutputStream zout;
|
||||
if (zout.open (fileStream, compressionLevel))
|
||||
{
|
||||
if (saveToStream (zout, flags, func))
|
||||
{
|
||||
result = zout.close ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!(flags & kNoPlainUIDescFileBackup))
|
||||
{
|
||||
// make a xml backup
|
||||
std::string backupFileName (filename);
|
||||
if (originalIsCompressed|| (flags & kForceWriteCompressedDesc))
|
||||
{
|
||||
if (flags & kWriteAsXML)
|
||||
backupFileName.append (".xml");
|
||||
else
|
||||
backupFileName.append (".json");
|
||||
}
|
||||
CFileStream xmlFileStream;
|
||||
if (xmlFileStream.open (backupFileName.data (),
|
||||
CFileStream::kWriteMode | CFileStream::kTruncateMode,
|
||||
kLittleEndianByteOrder))
|
||||
{
|
||||
result = saveToStream (xmlFileStream, flags, func);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // VSTGUI
|
||||
@@ -0,0 +1,48 @@
|
||||
// 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 "uidescription.h"
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace VSTGUI {
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
class CompressedUIDescription : public UIDescription
|
||||
{
|
||||
protected:
|
||||
enum CompressedSaveFlagBits
|
||||
{
|
||||
NoPlainUIDescFileBackupBit = UIDescription::LastSaveFlagBit,
|
||||
ForceWriteCompressedDesc,
|
||||
LastCompressedSaveFlagBit,
|
||||
};
|
||||
public:
|
||||
CompressedUIDescription (const CResourceDescription& compressedUIDescFile);
|
||||
|
||||
enum SaveFlags
|
||||
{
|
||||
kNoPlainUIDescFileBackup = 1 << NoPlainUIDescFileBackupBit,
|
||||
kForceWriteCompressedDesc = 1 << ForceWriteCompressedDesc,
|
||||
|
||||
kNoPlainXmlFileBackup [[deprecated("use kNoPlainUIDescFileBackup")]] = kNoPlainUIDescFileBackup,
|
||||
};
|
||||
|
||||
bool parse () override;
|
||||
bool save (UTF8StringPtr filename, int32_t flags = kWriteWindowsResourceFile,
|
||||
AttributeSaveFilterFunc func = nullptr) override;
|
||||
|
||||
bool getOriginalIsCompressed () const { return originalIsCompressed; }
|
||||
void setCompressionLevel (uint32_t level) { compressionLevel = level; }
|
||||
|
||||
private:
|
||||
bool parseWithStream (InputStream& stream);
|
||||
|
||||
bool originalIsCompressed {false};
|
||||
uint32_t compressionLevel {1};
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // VSTGUI
|
||||
@@ -0,0 +1,626 @@
|
||||
// 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 "cstream.h"
|
||||
#include "../lib/cresourcedescription.h"
|
||||
#include "../lib/malloc.h"
|
||||
#include "../lib/platform/iplatformresourceinputstream.h"
|
||||
#include "../lib/platform/platformfactory.h"
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
#if WINDOWS
|
||||
#define fseeko _fseeki64
|
||||
#define ftello _ftelli64
|
||||
#endif
|
||||
|
||||
namespace VSTGUI {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
CMemoryStream::CMemoryStream (uint32_t initialSize, uint32_t inDelta, bool binaryMode, ByteOrder byteOrder)
|
||||
: OutputStream (byteOrder)
|
||||
, InputStream (byteOrder)
|
||||
, buffer (nullptr)
|
||||
, bufferSize (0)
|
||||
, size (0)
|
||||
, pos (0)
|
||||
, delta (inDelta)
|
||||
, binaryMode (binaryMode)
|
||||
, ownsBuffer (true)
|
||||
{
|
||||
resize (initialSize);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
CMemoryStream::CMemoryStream (const int8_t* inBuffer, uint32_t bufferSize, bool binaryMode, ByteOrder byteOrder)
|
||||
: OutputStream (byteOrder)
|
||||
, InputStream (byteOrder)
|
||||
, buffer (const_cast<int8_t*> (inBuffer))
|
||||
, bufferSize (bufferSize)
|
||||
, size (bufferSize)
|
||||
, pos (0)
|
||||
, delta (0)
|
||||
, binaryMode (binaryMode)
|
||||
, ownsBuffer (false)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
CMemoryStream::~CMemoryStream () noexcept
|
||||
{
|
||||
if (ownsBuffer && buffer)
|
||||
std::free (buffer);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CMemoryStream::resize (uint32_t inSize)
|
||||
{
|
||||
if (bufferSize >= inSize)
|
||||
return true;
|
||||
|
||||
if (ownsBuffer == false)
|
||||
return false;
|
||||
|
||||
uint32_t newSize = bufferSize + delta;
|
||||
while (newSize < inSize)
|
||||
newSize += delta;
|
||||
|
||||
int8_t* newBuffer = (int8_t*)std::malloc (newSize);
|
||||
if (newBuffer && buffer)
|
||||
memcpy (newBuffer, buffer, size);
|
||||
if (buffer)
|
||||
std::free (buffer);
|
||||
buffer = newBuffer;
|
||||
bufferSize = newSize;
|
||||
|
||||
return buffer != nullptr;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
uint32_t CMemoryStream::writeRaw (const void* inBuffer, uint32_t inSize)
|
||||
{
|
||||
if (!resize (pos + inSize))
|
||||
return kStreamIOError;
|
||||
|
||||
memcpy (buffer + pos, inBuffer, inSize);
|
||||
pos += inSize;
|
||||
size = pos;
|
||||
|
||||
return inSize;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
uint32_t CMemoryStream::readRaw (void* outBuffer, uint32_t outSize)
|
||||
{
|
||||
if ((size - pos) <= 0)
|
||||
return 0;
|
||||
|
||||
outSize = std::min<uint32_t> (outSize, size - pos);
|
||||
memcpy (outBuffer, buffer + pos, outSize);
|
||||
pos += outSize;
|
||||
|
||||
return outSize;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int64_t CMemoryStream::seek (int64_t seekpos, SeekMode mode)
|
||||
{
|
||||
int64_t newPos;
|
||||
switch (mode)
|
||||
{
|
||||
case kSeekSet: newPos = seekpos; break;
|
||||
case kSeekCurrent: newPos = pos + seekpos; break;
|
||||
case kSeekEnd:
|
||||
default:
|
||||
newPos = size - seekpos;
|
||||
break;
|
||||
}
|
||||
if (newPos <= size && newPos > 0)
|
||||
{
|
||||
pos = static_cast<uint32_t> (newPos);
|
||||
return pos;
|
||||
}
|
||||
return kStreamSeekError;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CMemoryStream::operator>> (std::string& string)
|
||||
{
|
||||
if (binaryMode)
|
||||
{
|
||||
int32_t identifier;
|
||||
if (!(*static_cast<InputStream*> (this) >> identifier)) return false;
|
||||
if (identifier == 'str ')
|
||||
{
|
||||
uint32_t length;
|
||||
if (!(*static_cast<InputStream*> (this) >> length)) return false;
|
||||
Buffer<int8_t> buf (length);
|
||||
uint32_t read = readRaw (buf.data (), length);
|
||||
if (read == length)
|
||||
string.assign ((const char*)buf.data (), length);
|
||||
return read == length;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int8_t character;
|
||||
while (readRaw (&character, sizeof (character)) == sizeof (character))
|
||||
{
|
||||
if (character == 0)
|
||||
break;
|
||||
string.push_back (character);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CMemoryStream::operator<< (const std::string& str)
|
||||
{
|
||||
if (binaryMode)
|
||||
{
|
||||
if (!((*this) << (uint32_t)'str ')) return false;
|
||||
if (!((*this) << (uint32_t)str.length ())) return false;
|
||||
}
|
||||
return writeRaw (str.c_str (), static_cast<uint32_t> (str.length ())) == str.length ();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CMemoryStream::end ()
|
||||
{
|
||||
if (binaryMode == false)
|
||||
{
|
||||
const int8_t zero = 0;
|
||||
return writeRaw (&zero, 1) == 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
CFileStream::CFileStream ()
|
||||
: stream (nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
CFileStream::~CFileStream () noexcept
|
||||
{
|
||||
if (stream)
|
||||
{
|
||||
fclose (stream);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CFileStream::open (UTF8StringPtr path, int32_t mode, ByteOrder byteOrder)
|
||||
{
|
||||
if (stream)
|
||||
return false;
|
||||
InputStream::setByteOrder (byteOrder);
|
||||
OutputStream::setByteOrder (byteOrder);
|
||||
std::stringstream fmode;
|
||||
if (mode & kTruncateMode)
|
||||
{
|
||||
if (mode & kReadMode && mode & kWriteMode)
|
||||
fmode << "w+";
|
||||
else if (mode & kReadMode)
|
||||
fmode << "r";
|
||||
else if (mode & kWriteMode)
|
||||
fmode << "w";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mode & kReadMode && mode & kWriteMode)
|
||||
fmode << "a+";
|
||||
else if (mode & kWriteMode)
|
||||
fmode << "a";
|
||||
else if (mode & kReadMode)
|
||||
fmode << "r";
|
||||
else
|
||||
return false;
|
||||
}
|
||||
#if WINDOWS
|
||||
// always use binary mode so that newlines are not converted
|
||||
fmode << "b";
|
||||
#else
|
||||
if (mode & kBinaryMode)
|
||||
fmode << "b";
|
||||
#endif
|
||||
stream = fopen (path, fmode.str ().c_str ());
|
||||
openMode = mode;
|
||||
|
||||
return stream != nullptr;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool CFileStream::isEndOfFile () const
|
||||
{
|
||||
if (stream)
|
||||
{
|
||||
return feof (stream) != 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
uint32_t CFileStream::writeRaw (const void* buffer, uint32_t size)
|
||||
{
|
||||
if (stream)
|
||||
{
|
||||
uint32_t written = static_cast<uint32_t> (fwrite (buffer, size, 1, stream));
|
||||
return written * size;
|
||||
}
|
||||
return kStreamIOError;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
uint32_t CFileStream::readRaw (void* buffer, uint32_t size)
|
||||
{
|
||||
if (stream)
|
||||
{
|
||||
return static_cast<uint32_t> (fread (buffer, 1, size, stream));
|
||||
}
|
||||
return kStreamIOError;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int64_t CFileStream::seek (int64_t pos, SeekMode mode)
|
||||
{
|
||||
if (stream)
|
||||
{
|
||||
int fseekmode;
|
||||
switch (mode)
|
||||
{
|
||||
case kSeekSet: fseekmode = SEEK_SET; break;
|
||||
case kSeekCurrent: fseekmode = SEEK_CUR; break;
|
||||
case kSeekEnd:
|
||||
default:
|
||||
fseekmode = SEEK_END;
|
||||
break;
|
||||
}
|
||||
if (fseeko (stream, pos, fseekmode) == 0)
|
||||
return tell ();
|
||||
}
|
||||
return kStreamSeekError;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int64_t CFileStream::tell () const
|
||||
{
|
||||
if (stream)
|
||||
{
|
||||
return ftello (stream);
|
||||
}
|
||||
return kStreamSeekError;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void CFileStream::rewind ()
|
||||
{
|
||||
if (stream)
|
||||
{
|
||||
fseek (stream, 0, SEEK_SET);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CFileStream::operator>> (std::string& string)
|
||||
{
|
||||
int8_t character;
|
||||
string.clear ();
|
||||
while (readRaw (&character, sizeof (character)) == sizeof (character))
|
||||
{
|
||||
if (character == 0)
|
||||
break;
|
||||
string.push_back (character);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CFileStream::operator<< (const std::string& str)
|
||||
{
|
||||
if (writeRaw (str.c_str (), static_cast<uint32_t> (str.size ())) == str.size ())
|
||||
{
|
||||
if (openMode & kBinaryMode)
|
||||
{
|
||||
if (!((*this) << (int8_t)0))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
CResourceInputStream::CResourceInputStream (ByteOrder byteOrder)
|
||||
: InputStream (byteOrder)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
CResourceInputStream::~CResourceInputStream () noexcept
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CResourceInputStream::open (const CResourceDescription& res)
|
||||
{
|
||||
if (platformStream)
|
||||
return false;
|
||||
platformStream = getPlatformFactory ().createResourceInputStream (res);
|
||||
return platformStream != nullptr;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
uint32_t CResourceInputStream::readRaw (void* buffer, uint32_t size)
|
||||
{
|
||||
if (platformStream)
|
||||
return platformStream->readRaw (buffer, size);
|
||||
return kStreamIOError;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int64_t CResourceInputStream::seek (int64_t pos, SeekMode mode)
|
||||
{
|
||||
if (platformStream)
|
||||
{
|
||||
VSTGUI::SeekMode sm = VSTGUI::SeekMode::Set;
|
||||
switch (mode)
|
||||
{
|
||||
case kSeekCurrent: sm = VSTGUI::SeekMode::Current; break;
|
||||
case kSeekSet: sm = VSTGUI::SeekMode::Set; break;
|
||||
case kSeekEnd: sm = VSTGUI::SeekMode::End; break;
|
||||
}
|
||||
return platformStream->seek (pos, sm);
|
||||
}
|
||||
return kStreamSeekError;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int64_t CResourceInputStream::tell () const
|
||||
{
|
||||
if (platformStream)
|
||||
return platformStream->tell ();
|
||||
|
||||
return kStreamSeekError;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void CResourceInputStream::rewind ()
|
||||
{
|
||||
if (platformStream)
|
||||
platformStream->seek (0, VSTGUI::SeekMode::Set);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template<typename T>
|
||||
void endianSwap (T& value)
|
||||
{
|
||||
uint32_t size = sizeof (T);
|
||||
auto low = reinterpret_cast<uint8_t*> (&value);
|
||||
auto high = low + size - 1;
|
||||
while (size >= 2)
|
||||
{
|
||||
auto tmp = *low;
|
||||
*low = *high;
|
||||
*high = tmp;
|
||||
low += 2;
|
||||
high -= 2;
|
||||
size -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template<typename T>
|
||||
bool writeEndianSwap (const T& value, OutputStream& s)
|
||||
{
|
||||
auto tmp = value;
|
||||
endianSwap (tmp);
|
||||
return s.writeRaw (&tmp, sizeof (T)) == sizeof (T);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
bool OutputStream::operator<< (const int8_t& input)
|
||||
{
|
||||
return writeRaw (&input, sizeof (int8_t)) == sizeof (int8_t);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool OutputStream::operator<< (const uint8_t& input)
|
||||
{
|
||||
return writeRaw (&input, sizeof (uint8_t)) == sizeof (uint8_t);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool OutputStream::operator<< (const int16_t& input)
|
||||
{
|
||||
if (byteOrder == kNativeByteOrder)
|
||||
{
|
||||
return writeRaw (&input, sizeof (int16_t)) == sizeof (int16_t);
|
||||
}
|
||||
return writeEndianSwap (input, *this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool OutputStream::operator<< (const uint16_t& input)
|
||||
{
|
||||
if (byteOrder == kNativeByteOrder)
|
||||
{
|
||||
return writeRaw (&input, sizeof (uint16_t)) == sizeof (uint16_t);
|
||||
}
|
||||
return writeEndianSwap (input, *this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool OutputStream::operator<< (const int32_t& input)
|
||||
{
|
||||
if (byteOrder == kNativeByteOrder)
|
||||
{
|
||||
return writeRaw (&input, sizeof (int32_t)) == sizeof (int32_t);
|
||||
}
|
||||
return writeEndianSwap (input, *this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool OutputStream::operator<< (const uint32_t& input)
|
||||
{
|
||||
if (byteOrder == kNativeByteOrder)
|
||||
{
|
||||
return writeRaw (&input, sizeof (uint32_t)) == sizeof (uint32_t);
|
||||
}
|
||||
return writeEndianSwap (input, *this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool OutputStream::operator<< (const int64_t& input)
|
||||
{
|
||||
if (byteOrder == kNativeByteOrder)
|
||||
{
|
||||
return writeRaw (&input, sizeof (int64_t)) == sizeof (int64_t);
|
||||
}
|
||||
return writeEndianSwap (input, *this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool OutputStream::operator<< (const uint64_t& input)
|
||||
{
|
||||
if (byteOrder == kNativeByteOrder)
|
||||
{
|
||||
return writeRaw (&input, sizeof (uint64_t)) == sizeof (uint64_t);
|
||||
}
|
||||
return writeEndianSwap (input, *this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool OutputStream::operator<< (const double& input)
|
||||
{
|
||||
if (byteOrder == kNativeByteOrder)
|
||||
{
|
||||
return writeRaw (&input, sizeof (double)) == sizeof (double);
|
||||
}
|
||||
return writeEndianSwap (input, *this);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
bool InputStream::operator>> (int8_t& output)
|
||||
{
|
||||
return readRaw (&output, sizeof (int8_t)) == sizeof (int8_t);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool InputStream::operator>> (uint8_t& output)
|
||||
{
|
||||
return readRaw (&output, sizeof (uint8_t)) == sizeof (uint8_t);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool InputStream::operator>> (int16_t& output)
|
||||
{
|
||||
if (readRaw (&output, sizeof (int16_t)) == sizeof (int16_t))
|
||||
{
|
||||
if (byteOrder != kNativeByteOrder)
|
||||
{
|
||||
endianSwap (output);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool InputStream::operator>> (uint16_t& output)
|
||||
{
|
||||
if (readRaw (&output, sizeof (uint16_t)) == sizeof (uint16_t))
|
||||
{
|
||||
if (byteOrder != kNativeByteOrder)
|
||||
{
|
||||
endianSwap (output);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool InputStream::operator>> (int32_t& output)
|
||||
{
|
||||
if (readRaw (&output, sizeof (int32_t)) == sizeof (int32_t))
|
||||
{
|
||||
if (byteOrder != kNativeByteOrder)
|
||||
{
|
||||
endianSwap (output);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool InputStream::operator>> (uint32_t& output)
|
||||
{
|
||||
if (readRaw (&output, sizeof (uint32_t)) == sizeof (uint32_t))
|
||||
{
|
||||
if (byteOrder != kNativeByteOrder)
|
||||
{
|
||||
endianSwap (output);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool InputStream::operator>> (int64_t& output)
|
||||
{
|
||||
if (readRaw (&output, sizeof (int64_t)) == sizeof (int64_t))
|
||||
{
|
||||
if (byteOrder != kNativeByteOrder)
|
||||
{
|
||||
endianSwap (output);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool InputStream::operator>> (uint64_t& output)
|
||||
{
|
||||
if (readRaw (&output, sizeof (uint64_t)) == sizeof (uint64_t))
|
||||
{
|
||||
if (byteOrder != kNativeByteOrder)
|
||||
{
|
||||
endianSwap (output);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool InputStream::operator>> (double& output)
|
||||
{
|
||||
if (readRaw (&output, sizeof (double)) == sizeof (double))
|
||||
{
|
||||
if (byteOrder != kNativeByteOrder)
|
||||
{
|
||||
endianSwap (output);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // VSTGUI
|
||||
@@ -0,0 +1,304 @@
|
||||
// This file is part of VSTGUI. It is subject to the license terms
|
||||
// in the LICENSE file found in the top-level directory of this
|
||||
// distribution and at http://github.com/steinbergmedia/vstgui/LICENSE
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../lib/vstguifwd.h"
|
||||
#include "../lib/optional.h"
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
namespace VSTGUI {
|
||||
|
||||
/**
|
||||
ByteOrder aware output stream interface
|
||||
*/
|
||||
class OutputStream
|
||||
{
|
||||
public:
|
||||
explicit OutputStream (ByteOrder byteOrder = kNativeByteOrder) : byteOrder (byteOrder) {}
|
||||
virtual ~OutputStream () noexcept = default;
|
||||
|
||||
ByteOrder getByteOrder () const { return byteOrder; }
|
||||
void setByteOrder (ByteOrder newByteOrder) { byteOrder = newByteOrder; }
|
||||
|
||||
bool operator<< (const int8_t& input);
|
||||
bool operator<< (const uint8_t& input);
|
||||
bool operator<< (const int16_t& input);
|
||||
bool operator<< (const uint16_t& input);
|
||||
bool operator<< (const int32_t& input);
|
||||
bool operator<< (const uint32_t& input);
|
||||
bool operator<< (const int64_t& input);
|
||||
bool operator<< (const uint64_t& input);
|
||||
bool operator<< (const double& input);
|
||||
|
||||
virtual bool operator<< (const std::string& str) = 0;
|
||||
|
||||
virtual uint32_t writeRaw (const void* buffer, uint32_t size) = 0;
|
||||
private:
|
||||
ByteOrder byteOrder;
|
||||
};
|
||||
|
||||
/**
|
||||
ByteOrder aware input stream interface
|
||||
*/
|
||||
class InputStream
|
||||
{
|
||||
public:
|
||||
explicit InputStream (ByteOrder byteOrder = kNativeByteOrder) : byteOrder (byteOrder) {}
|
||||
virtual ~InputStream () noexcept = default;
|
||||
|
||||
ByteOrder getByteOrder () const { return byteOrder; }
|
||||
void setByteOrder (ByteOrder newByteOrder) { byteOrder = newByteOrder; }
|
||||
|
||||
bool operator>> (int8_t& output);
|
||||
bool operator>> (uint8_t& output);
|
||||
bool operator>> (int16_t& output);
|
||||
bool operator>> (uint16_t& output);
|
||||
bool operator>> (int32_t& output);
|
||||
bool operator>> (uint32_t& output);
|
||||
bool operator>> (int64_t& output);
|
||||
bool operator>> (uint64_t& output);
|
||||
bool operator>> (double& output);
|
||||
|
||||
virtual bool operator>> (std::string& string) = 0;
|
||||
|
||||
virtual uint32_t readRaw (void* buffer, uint32_t size) = 0;
|
||||
private:
|
||||
ByteOrder byteOrder;
|
||||
};
|
||||
|
||||
/**
|
||||
Seekable stream interface
|
||||
*/
|
||||
class SeekableStream
|
||||
{
|
||||
public:
|
||||
virtual ~SeekableStream () noexcept = default;
|
||||
enum SeekMode {
|
||||
kSeekSet,
|
||||
kSeekCurrent,
|
||||
kSeekEnd
|
||||
};
|
||||
|
||||
/** returns -1 if seek fails otherwise new position */
|
||||
virtual int64_t seek (int64_t pos, SeekMode mode) = 0;
|
||||
virtual int64_t tell () const = 0;
|
||||
virtual void rewind () = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
Memory input and output stream
|
||||
*/
|
||||
class CMemoryStream : virtual public OutputStream, virtual public InputStream, public SeekableStream, public AtomicReferenceCounted
|
||||
{
|
||||
public:
|
||||
CMemoryStream (uint32_t initialSize = 1024, uint32_t delta = 1024, bool binaryMode = true, ByteOrder byteOrder = kNativeByteOrder);
|
||||
CMemoryStream (const int8_t* buffer, uint32_t bufferSize, bool binaryMode = true, ByteOrder byteOrder = kNativeByteOrder);
|
||||
~CMemoryStream () noexcept override;
|
||||
|
||||
uint32_t writeRaw (const void* buffer, uint32_t size) override;
|
||||
uint32_t readRaw (void* buffer, uint32_t size) override;
|
||||
|
||||
int64_t seek (int64_t pos, SeekMode mode) override;
|
||||
int64_t tell () const override { return static_cast<int64_t> (pos); }
|
||||
void rewind () override { pos = 0; }
|
||||
|
||||
const int8_t* getBuffer () const { return buffer; }
|
||||
|
||||
bool operator<< (const std::string& str) override;
|
||||
bool operator>> (std::string& string) override;
|
||||
|
||||
using OutputStream::operator<<;
|
||||
using InputStream::operator>>;
|
||||
|
||||
bool end (); // write a zero byte if binaryMode is false
|
||||
protected:
|
||||
bool resize (uint32_t newSize);
|
||||
|
||||
int8_t* buffer;
|
||||
uint32_t bufferSize;
|
||||
uint32_t size;
|
||||
uint32_t pos;
|
||||
uint32_t delta;
|
||||
bool binaryMode;
|
||||
bool ownsBuffer;
|
||||
};
|
||||
|
||||
/**
|
||||
File input and output stream
|
||||
*/
|
||||
class CFileStream : public OutputStream, public InputStream, public SeekableStream, public AtomicReferenceCounted
|
||||
{
|
||||
public:
|
||||
CFileStream ();
|
||||
~CFileStream () noexcept override;
|
||||
|
||||
enum {
|
||||
kReadMode = 1 << 0,
|
||||
kWriteMode = 1 << 1,
|
||||
kTruncateMode = 1 << 2,
|
||||
kBinaryMode = 1 << 3
|
||||
};
|
||||
|
||||
bool open (UTF8StringPtr path, int32_t mode, ByteOrder byteOrder = kNativeByteOrder);
|
||||
bool isEndOfFile () const;
|
||||
|
||||
uint32_t writeRaw (const void* buffer, uint32_t size) override;
|
||||
uint32_t readRaw (void* buffer, uint32_t size) override;
|
||||
|
||||
int64_t seek (int64_t pos, SeekMode mode) override;
|
||||
int64_t tell () const override;
|
||||
void rewind () override;
|
||||
|
||||
bool operator<< (const std::string& str) override;
|
||||
bool operator>> (std::string& string) override;
|
||||
|
||||
using OutputStream::operator<<;
|
||||
using InputStream::operator>>;
|
||||
protected:
|
||||
FILE* stream;
|
||||
int32_t openMode;
|
||||
};
|
||||
|
||||
static const int8_t unixPathSeparator = '/';
|
||||
static const int8_t windowsPathSeparator = '\\';
|
||||
/**
|
||||
Helper function to transform all Windows path separators to unix ones
|
||||
*/
|
||||
inline void unixfyPath (std::string& path)
|
||||
{
|
||||
std::replace (path.begin (), path.end (), windowsPathSeparator, unixPathSeparator);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline bool removeLastPathComponent (std::string& path)
|
||||
{
|
||||
size_t sepPos = path.find_last_of (unixPathSeparator);
|
||||
if (sepPos != std::string::npos)
|
||||
{
|
||||
path.erase (sepPos);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline Optional<std::string> lastPathComponent (const std::string path)
|
||||
{
|
||||
size_t sepPos = path.find_last_of (unixPathSeparator);
|
||||
if (sepPos == std::string::npos)
|
||||
return Optional<std::string> (path);
|
||||
return {path.substr (sepPos + 1)};
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline bool pathIsAbsolute (const std::string& path)
|
||||
{
|
||||
#if MAC || LINUX
|
||||
return !path.empty () && path[0] == unixPathSeparator;
|
||||
#elif WINDOWS
|
||||
return path.length () >= 2 && path[1] == ':';
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
Resource input stream
|
||||
*/
|
||||
class CResourceInputStream : public InputStream, public SeekableStream
|
||||
{
|
||||
public:
|
||||
explicit CResourceInputStream (ByteOrder byteOrder = kNativeByteOrder);
|
||||
~CResourceInputStream () noexcept override;
|
||||
|
||||
bool open (const CResourceDescription& res);
|
||||
|
||||
bool operator>> (std::string& string) override { return false; }
|
||||
uint32_t readRaw (void* buffer, uint32_t size) override;
|
||||
int64_t seek (int64_t pos, SeekMode mode) override;
|
||||
int64_t tell () const override;
|
||||
void rewind () override;
|
||||
|
||||
using InputStream::operator>>;
|
||||
protected:
|
||||
PlatformResourceInputStreamPtr platformStream;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
class BufferedOutputStream : public OutputStream
|
||||
{
|
||||
public:
|
||||
BufferedOutputStream (OutputStream& stream, size_t bufferSize = 8192)
|
||||
: stream (stream), bufferSize (bufferSize)
|
||||
{
|
||||
buffer.reserve (bufferSize);
|
||||
}
|
||||
~BufferedOutputStream () noexcept override { flush (); }
|
||||
bool operator<< (const std::string& str) override
|
||||
{
|
||||
return writeRaw (str.c_str (), static_cast<uint32_t> (str.size ())) == str.size ();
|
||||
}
|
||||
uint32_t writeRaw (const void* inBuffer, uint32_t size) override
|
||||
{
|
||||
auto written = size;
|
||||
const uint8_t* ptr = reinterpret_cast<const uint8_t*> (inBuffer);
|
||||
while (size)
|
||||
{
|
||||
auto toWrite = 1;
|
||||
buffer.emplace_back (*ptr);
|
||||
if (buffer.size () == bufferSize)
|
||||
{
|
||||
if (!flush ())
|
||||
return kStreamIOError;
|
||||
}
|
||||
size -= toWrite;
|
||||
ptr += toWrite;
|
||||
}
|
||||
return written;
|
||||
}
|
||||
bool flush ()
|
||||
{
|
||||
if (buffer.empty ())
|
||||
return true;
|
||||
auto result = stream.writeRaw (buffer.data (), static_cast<uint32_t> (buffer.size ())) ==
|
||||
buffer.size ();
|
||||
buffer.clear ();
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
OutputStream& stream;
|
||||
std::vector<uint8_t> buffer;
|
||||
size_t bufferSize;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
class StdOutStream : public OutputStream
|
||||
{
|
||||
public:
|
||||
StdOutStream () {}
|
||||
uint32_t writeRaw (const void* buffer, uint32_t size) override
|
||||
{
|
||||
auto byteBuffer = reinterpret_cast<const uint8_t*>(buffer);
|
||||
for (auto i = 0u; i < size; ++i, ++byteBuffer)
|
||||
{
|
||||
std::cout << *byteBuffer;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
bool operator<< (const std::string& str) override
|
||||
{
|
||||
std::cout << str;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // VSTGUI
|
||||
@@ -0,0 +1,206 @@
|
||||
// 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 "cstream_zlib.h"
|
||||
#include <array>
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace VSTGUI {
|
||||
|
||||
namespace {
|
||||
#if _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4334)
|
||||
#endif
|
||||
#define MINIZ_NO_STDIO
|
||||
#define MINIZ_NO_ARCHIVE_APIS
|
||||
#define MINIZ_NO_ARCHIVE_WRITING_APIS
|
||||
#include "../thirdparty/miniz/miniz.c"
|
||||
#if _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
using z_stream = mz_stream;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct ZLibInputStream::Impl
|
||||
{
|
||||
z_stream zstream {};
|
||||
InputStream* stream {nullptr};
|
||||
std::array<Bytef, 4096> internalBuffer;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct ZLibOutputStream::Impl
|
||||
{
|
||||
z_stream zstream {};
|
||||
OutputStream* stream {nullptr};
|
||||
std::array<Bytef, 4096> internalBuffer;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
ZLibInputStream::ZLibInputStream (ByteOrder byteOrder) : InputStream (byteOrder)
|
||||
{
|
||||
impl = std::make_unique<Impl> ();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
ZLibInputStream::~ZLibInputStream () noexcept
|
||||
{
|
||||
if (impl->zstream.next_in != nullptr)
|
||||
inflateEnd (&impl->zstream);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ZLibInputStream::open (InputStream& _stream)
|
||||
{
|
||||
if (impl->zstream.next_in != nullptr || impl->stream != nullptr)
|
||||
return false;
|
||||
impl->stream = &_stream;
|
||||
|
||||
auto read = impl->stream->readRaw (impl->internalBuffer.data (),
|
||||
static_cast<uint32_t> (impl->internalBuffer.size ()));
|
||||
if (read == 0 || read == kStreamIOError)
|
||||
return false;
|
||||
|
||||
impl->zstream.next_in = impl->internalBuffer.data ();
|
||||
impl->zstream.avail_in = read;
|
||||
|
||||
if (inflateInit (&impl->zstream) != Z_OK)
|
||||
{
|
||||
impl->zstream = {};
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
uint32_t ZLibInputStream::readRaw (void* buffer, uint32_t size)
|
||||
{
|
||||
if (impl->zstream.next_in == nullptr || !buffer)
|
||||
return kStreamIOError;
|
||||
impl->zstream.next_out = static_cast<Bytef*> (buffer);
|
||||
impl->zstream.avail_out = size;
|
||||
while (impl->zstream.avail_out > 0)
|
||||
{
|
||||
if (impl->zstream.avail_in == 0)
|
||||
{
|
||||
auto read = impl->stream->readRaw (
|
||||
impl->internalBuffer.data (), static_cast<uint32_t> (impl->internalBuffer.size ()));
|
||||
if (read > 0 && read != kStreamIOError)
|
||||
{
|
||||
impl->zstream.next_in = impl->internalBuffer.data ();
|
||||
impl->zstream.avail_in = read;
|
||||
}
|
||||
}
|
||||
auto zres = inflate (&impl->zstream, Z_SYNC_FLUSH);
|
||||
if (zres == Z_STREAM_END)
|
||||
{
|
||||
return size - impl->zstream.avail_out;
|
||||
}
|
||||
else if (zres != Z_OK)
|
||||
return kStreamIOError;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
ZLibOutputStream::ZLibOutputStream (ByteOrder byteOrder) : OutputStream (byteOrder)
|
||||
{
|
||||
impl = std::make_unique<Impl> ();
|
||||
impl->zstream.opaque = this;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
ZLibOutputStream::~ZLibOutputStream () noexcept { close (); }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ZLibOutputStream::open (OutputStream& _stream, int32_t compressionLevel)
|
||||
{
|
||||
if (impl->zstream.opaque != nullptr || impl->stream != nullptr)
|
||||
return false;
|
||||
impl->stream = &_stream;
|
||||
|
||||
if (deflateInit (&impl->zstream, compressionLevel) != Z_OK)
|
||||
{
|
||||
impl->zstream = {};
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ZLibOutputStream::close ()
|
||||
{
|
||||
bool result = true;
|
||||
if (impl->zstream.opaque == this)
|
||||
{
|
||||
impl->zstream.next_in = nullptr;
|
||||
impl->zstream.avail_in = 0;
|
||||
while (true)
|
||||
{
|
||||
impl->zstream.next_out = impl->internalBuffer.data ();
|
||||
impl->zstream.avail_out = static_cast<unsigned int> (impl->internalBuffer.size ());
|
||||
auto zres = deflate (&impl->zstream, Z_FINISH);
|
||||
if (zres != Z_OK && zres != Z_BUF_ERROR && zres != Z_STREAM_END)
|
||||
{
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
else if (impl->zstream.avail_out != impl->internalBuffer.size ())
|
||||
{
|
||||
auto written = impl->stream->writeRaw (
|
||||
impl->internalBuffer.data (),
|
||||
static_cast<uint32_t> (impl->internalBuffer.size () - impl->zstream.avail_out));
|
||||
if (written != impl->internalBuffer.size () - impl->zstream.avail_out)
|
||||
{
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (zres == Z_STREAM_END)
|
||||
break;
|
||||
}
|
||||
deflateEnd (&impl->zstream);
|
||||
impl->zstream = {};
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
uint32_t ZLibOutputStream::writeRaw (const void* buffer, uint32_t size)
|
||||
{
|
||||
if (impl->zstream.opaque != this)
|
||||
return kStreamIOError;
|
||||
impl->zstream.next_in = const_cast<Bytef*> (static_cast<const Bytef*> (buffer));
|
||||
impl->zstream.avail_in = size;
|
||||
while (impl->zstream.avail_in > 0)
|
||||
{
|
||||
impl->zstream.next_out = impl->internalBuffer.data ();
|
||||
impl->zstream.avail_out = static_cast<unsigned int> (impl->internalBuffer.size ());
|
||||
auto zres = deflate (&impl->zstream, Z_NO_FLUSH);
|
||||
if (zres == Z_STREAM_ERROR)
|
||||
{
|
||||
return kStreamIOError;
|
||||
}
|
||||
if (impl->zstream.avail_out != impl->internalBuffer.size ())
|
||||
{
|
||||
auto written = impl->stream->writeRaw (
|
||||
impl->internalBuffer.data (),
|
||||
static_cast<uint32_t> (impl->internalBuffer.size () - impl->zstream.avail_out));
|
||||
if (written != impl->internalBuffer.size () - impl->zstream.avail_out)
|
||||
return kStreamIOError;
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // VSTGUI
|
||||
@@ -0,0 +1,51 @@
|
||||
// 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"
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace VSTGUI {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class ZLibInputStream : public InputStream
|
||||
{
|
||||
public:
|
||||
ZLibInputStream (ByteOrder byteOrder = kNativeByteOrder);
|
||||
~ZLibInputStream () noexcept;
|
||||
|
||||
bool open (InputStream& stream);
|
||||
|
||||
bool operator>> (std::string& string) override { return false; }
|
||||
uint32_t readRaw (void* buffer, uint32_t size) override;
|
||||
|
||||
private:
|
||||
struct Impl;
|
||||
std::unique_ptr<Impl> impl;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class ZLibOutputStream : public OutputStream
|
||||
{
|
||||
public:
|
||||
ZLibOutputStream (ByteOrder byteOrder = kNativeByteOrder);
|
||||
~ZLibOutputStream () noexcept;
|
||||
|
||||
bool open (OutputStream& stream, int32_t compressionLevel = 6);
|
||||
bool close ();
|
||||
|
||||
bool operator<< (const std::string& str) override
|
||||
{
|
||||
return writeRaw (str.data (), static_cast<uint32_t> (str.size ())) == str.size ();
|
||||
}
|
||||
uint32_t writeRaw (const void* buffer, uint32_t size) override;
|
||||
|
||||
private:
|
||||
struct Impl;
|
||||
std::unique_ptr<Impl> impl;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // VSTGUI
|
||||
@@ -0,0 +1,34 @@
|
||||
// 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 "icontroller.h"
|
||||
|
||||
namespace VSTGUI {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class DelegationController : public IController
|
||||
{
|
||||
public:
|
||||
explicit DelegationController (IController* controller) : controller (controller) {}
|
||||
|
||||
// IControlListener
|
||||
void valueChanged (CControl* pControl) override { controller->valueChanged (pControl); }
|
||||
int32_t controlModifierClicked (CControl* pControl, CButtonState button) override { return controller->controlModifierClicked (pControl, button); }
|
||||
void controlBeginEdit (CControl* pControl) override { controller->controlBeginEdit (pControl); }
|
||||
void controlEndEdit (CControl* pControl) override { controller->controlEndEdit (pControl); }
|
||||
void controlTagWillChange (VSTGUI::CControl* pControl) override { controller->controlTagWillChange (pControl); }
|
||||
void controlTagDidChange (VSTGUI::CControl* pControl) override { controller->controlTagDidChange (pControl); }
|
||||
// IController
|
||||
int32_t getTagForName (UTF8StringPtr name, int32_t registeredTag) const override { return controller->getTagForName (name, registeredTag); }
|
||||
IControlListener* getControlListener (UTF8StringPtr name) override { return controller->getControlListener (name); }
|
||||
CView* createView (const UIAttributes& attributes, const IUIDescription* description) override { return controller->createView (attributes, description); }
|
||||
CView* verifyView (CView* view, const UIAttributes& attributes, const IUIDescription* description) override { return controller->verifyView (view, attributes, description); }
|
||||
IController* createSubController (IdStringPtr name, const IUIDescription* description) override { return controller->createSubController (name, description); }
|
||||
protected:
|
||||
IController* controller;
|
||||
};
|
||||
|
||||
} // VSTGUI
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
|
||||
@page uidescription Creating user interfaces
|
||||
|
||||
You can create user interfaces in VSTGUI via an uidescription file instead of using c++ code to create views and controls, just controller code needs to be coded in c++.
|
||||
|
||||
> The format has changed from XML to JSON in version 4.10, due to security and performance characteristics of XML and JSON.
|
||||
|
||||
It's preferred to not write the JSON file by hand, but use the included WYSIWYG editor.
|
||||
You can use the editor when targeting a standalone application or an editor for a VST3 plug-in. If you need this for something else you can write the glue code yourself.
|
||||
|
||||
- @subpage page_uidescription_editor
|
||||
- @subpage the_view_system
|
||||
- @subpage create_your_own_view
|
||||
- @ref standalone_library
|
||||
|
||||
<hr/>
|
||||
|
||||
> For the old documentation see @subpage uidescriptionXML
|
||||
|
||||
*/
|
||||
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
echo `pwd`
|
||||
mkdir -p "$1"
|
||||
|
||||
rm -f "$1/editoruidesc.h"
|
||||
echo -n "constexpr auto editorUIDesc = R\"====(" >> "$1/editoruidesc.h"
|
||||
cat uidescriptioneditor.uidesc >> "$1/editoruidesc.h"
|
||||
echo ")====\";" >> "$1/editoruidesc.h"
|
||||
|
||||
echo -n "constexpr auto editorUILightDesc = R\"====(" >> "$1/editoruidesc.h"
|
||||
cat uidescriptioneditor_res_light.uidesc >> "$1/editoruidesc.h"
|
||||
echo ")====\";" >> "$1/editoruidesc.h"
|
||||
|
||||
echo -n "constexpr auto editorUIDarkDesc = R\"====(" >> "$1/editoruidesc.h"
|
||||
cat uidescriptioneditor_res_dark.uidesc >> "$1/editoruidesc.h"
|
||||
echo ")====\";" >> "$1/editoruidesc.h"
|
||||
|
||||
@@ -0,0 +1,328 @@
|
||||
// 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
|
||||
|
||||
/*
|
||||
|
||||
TODO:
|
||||
Musts:
|
||||
- fix TODOs
|
||||
- finish documentation
|
||||
|
||||
Nice To Have:
|
||||
- grid handling improvements (like custom magnetic lines)
|
||||
- more custom attribute editing
|
||||
- view z-index editing via drag&drop
|
||||
- editing of uidescription variables
|
||||
|
||||
Known Bugs:
|
||||
- sometimes the attribute editor is not editable (dont know why yet)
|
||||
- setting autosize of template seems not to work
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
@page page_uidescription_editor Inline UI Editor for VST3 (WYSIWYG)
|
||||
|
||||
@tableofcontents
|
||||
|
||||
@section ui_editor_intro Introduction
|
||||
|
||||
VSTGUI 4.1 includes a new VST3 inline UI editor which makes UI design easier than before.
|
||||
|
||||
It automatically supports the following VST3 features:
|
||||
- IParameterFinder (find parameter under mouse)
|
||||
- IContextMenu (show host context menu on right click for an automatable parameter) [VST3.5 SDK required]
|
||||
|
||||
@note You need at least VST SDK 3.1, any earlier version will not work.
|
||||
@note The new editor is compatible to the old one included in VSTGUI 4.0
|
||||
|
||||
<hr/>
|
||||
|
||||
@section ui_editor_preparation Preparation
|
||||
|
||||
Before using the inline UI editor, you must make sure that you use the Steinberg::Vst::EditController class as a base
|
||||
of your own edit controller and that you have used the Steinberg::Vst::Parameter class or any subclass of it for your
|
||||
parameters.<br>
|
||||
Otherwise the inline UI editor won't work properly.
|
||||
|
||||
Next you have to add two files to your project:
|
||||
- vstgui/vstgui_uidescription.cpp
|
||||
- vstgui/plugin-bindings/vst3editor.cpp
|
||||
|
||||
After that you have to alter your project settings to add a preprocessor definition to your debug build:
|
||||
- VSTGUI_LIVE_EDITING=1
|
||||
|
||||
As last step you have to modify your edit controller class to overwrite the createView() method:
|
||||
@code
|
||||
IPlugView* PLUGIN_API MyEditController::createView (FIDString name)
|
||||
{
|
||||
if (strcmp (name, ViewType::kEditor) == 0)
|
||||
{
|
||||
return new VSTGUI::VST3Editor (this, "view", "myEditor.uidesc");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@endcode
|
||||
|
||||
And make sure to include the vst3editor.h header.
|
||||
|
||||
Now you can build your plug-in and start your preferred VST3 host to start designing your user interface.
|
||||
|
||||
If you now open your plug-in editor you will see a blank editor. To enter the UI editor you have to make a
|
||||
right click on it and choose "Open UIDescription Editor".
|
||||
|
||||
\note Your VST3 host should support live plug-in resizing for optimal experience. As of this writing, not all VST3 hosts support this feature.
|
||||
|
||||
<hr/>
|
||||
|
||||
@section ui_editor_parameter_binding Parameter Binding
|
||||
|
||||
If you've used the Parameter class provided by the VST3 SDK, you will get automatic parameter bindings between the controls of your editor
|
||||
and the parameters in your VST Edit Controller.
|
||||
|
||||
The only thing you need to do is to declare the ids of the parameters as tags in the @ref the_editor_view_palette_globals_tags editor
|
||||
(or use the 'Sync Parameter Tags' command in the Edit Menu of the @ref the_editor_toolbar) and set the tags of your controls to these ids.
|
||||
After you've done this your VST Edit Controller will receive the beginEdit(..)/performEdit(..)/endEdit(..) calls when the user changes the controls and if the host
|
||||
automates the parameter the control will also reflect these changes.
|
||||
|
||||
As an addition you can modify your VST Edit Controller to return specific parameter objects in the getParameterObject(int32 paramID) method for UI only needs, which are not
|
||||
parameters of your VST audio processor. This way you can store view settings like the tab which is open when the user closes the editor so that you can restore it
|
||||
when the user opens the editor again. You can look at the sources of the included 'uidescription test' project how this works.
|
||||
|
||||
<hr/>
|
||||
|
||||
<img src="ui_editor.png" style="float:right"/>
|
||||
|
||||
@section ui_editor_the_editor The Editor
|
||||
|
||||
The Editor has mainly five sections:
|
||||
<ol>
|
||||
<li>@ref the_editor_toolbar @n</li>
|
||||
<li>@ref the_editor_template_editor @n</li>
|
||||
<li>@ref the_editor_view_attribute_editor @n</li>
|
||||
<li>@ref the_editor_template_view_hierarchy @n</li>
|
||||
<li>@ref the_editor_view_palette_globals @n</li>
|
||||
</ol>
|
||||
|
||||
All actions you do here are undoable.
|
||||
|
||||
<div style="clear:both"></div>
|
||||
<hr/>
|
||||
|
||||
@subsection the_editor_toolbar Toolbar
|
||||
|
||||
The toolbar currently contains the two menus "File" and "Edit", the editing checkbox and the grid settings.
|
||||
|
||||
TODO: describe menu items
|
||||
|
||||
The File Menu contains:
|
||||
- Save
|
||||
- Save as...
|
||||
- Close Editor
|
||||
|
||||
The Edit Menu contains:
|
||||
- Undo
|
||||
- Redo
|
||||
- Cut
|
||||
- Copy
|
||||
- Paste
|
||||
- Delete
|
||||
- Size To Fit
|
||||
- Unembed Views
|
||||
- Embed Into
|
||||
- Transform View Type
|
||||
- Add New Template
|
||||
- Delete Template
|
||||
- Duplicate Template
|
||||
- Template Settings...
|
||||
- Focus Settings...
|
||||
- Sync Parameter Tags
|
||||
|
||||
<hr/>
|
||||
|
||||
@subsection the_editor_template_editor Template Editor
|
||||
|
||||
TODO
|
||||
|
||||
<hr/>
|
||||
|
||||
@subsection the_editor_view_attribute_editor View Attribute Editor
|
||||
|
||||
The View Attribute Editor shows the attributes of the selected views. If multiple views are selected
|
||||
it only shows those attributes which applies to all selected views.
|
||||
On the left side are the names of the attributes and on the right side their values. The values are editable.
|
||||
|
||||
You can enter a search term in the search field so that only those attributes are shown which matches the search string.
|
||||
|
||||
<hr/>
|
||||
|
||||
@subsection the_editor_template_view_hierarchy Template Selector + View Hierarchy Browser
|
||||
|
||||
The most left list shows all the templates. You can rename a template with a double click on it.
|
||||
|
||||
If a template is selected, it is shown in the Template Editor and all sub
|
||||
views are listed in the next list. You can select these sub views and if the selected sub view is a container view,
|
||||
its subviews are listed in the next list, etc.
|
||||
|
||||
You can alter the selection of the Template Editor via double click.
|
||||
|
||||
You can move the selected view up and down in the hierarchy order via Command-Up and Command-Down.
|
||||
|
||||
<hr/>
|
||||
|
||||
@subsection the_editor_view_palette_globals View Palette + Global UI Properties Editor
|
||||
|
||||
This section contains five subsections :
|
||||
- @ref the_editor_view_palette_globals_view @n
|
||||
- @ref the_editor_view_palette_globals_tags @n
|
||||
- @ref the_editor_view_palette_globals_colors @n
|
||||
- @ref the_editor_view_palette_globals_bitmaps @n
|
||||
- @ref the_editor_view_palette_globals_fonts @n
|
||||
|
||||
<hr/>
|
||||
|
||||
<img src="ui_editor_views_browser.png" style="display:block; float:right"/>
|
||||
@subsubsection the_editor_view_palette_globals_view Views
|
||||
|
||||
This section shows all views which are registered with UIDescription. You can register your own views,
|
||||
see \ref VSTGUI::IViewCreator.
|
||||
|
||||
To insert a view, select it and drag it into the template editor. While dragging the view over the template editor, the
|
||||
container view will be highlighted which will be the parent of the view if you drop it there.
|
||||
|
||||
<div style="clear:both"></div>
|
||||
<hr/>
|
||||
|
||||
<img src="ui_editor_tags_browser.png" style="float:right"/>
|
||||
@subsubsection the_editor_view_palette_globals_tags Tags
|
||||
|
||||
Here you define Tags for your controls. The left column describes the name of the Tag and the right column is the
|
||||
numerical value of the tag as used in VSTGUI::CControl.
|
||||
|
||||
With the + button you add a new tag and with the - button you remove the selected tag.
|
||||
|
||||
<div style="clear:both"></div>
|
||||
<hr/>
|
||||
|
||||
<img src="ui_editor_colors_browser.png" style="float:right"/>
|
||||
@subsubsection the_editor_view_palette_globals_colors Colors
|
||||
|
||||
TODO: New Screenshot
|
||||
|
||||
Here you define custom colors.
|
||||
|
||||
With the + button you add a new color and with the - button you remove the selected color.
|
||||
|
||||
<div style="clear:both"></div>
|
||||
<hr/>
|
||||
|
||||
<img src="ui_editor_bitmaps_browser.png" style="float:right"/>
|
||||
@subsubsection the_editor_view_palette_globals_bitmaps Bitmaps
|
||||
|
||||
TODO: New Screenshot
|
||||
|
||||
Here you define your bitmaps.
|
||||
|
||||
The path is the path to the bitmap.
|
||||
- On Mac OS X this is the filename of the bitmap inside the Resources directory of the plug-in bundle.
|
||||
- On Windows this is the resource name as described in the .rc file of your plug-in.
|
||||
|
||||
The Nine Part Tiled checkbox indicates if this is a VSTGUI::CNinePartTiledBitmap. And the l/t/r/b values describes its offsets.
|
||||
|
||||
With the + button you add a new bitmap and with the - button you remove the selected bitmap.
|
||||
|
||||
<div style="clear:both"></div>
|
||||
<hr/>
|
||||
|
||||
<img src="ui_editor_fonts_browser.png" style="float:right"/>
|
||||
@subsubsection the_editor_view_palette_globals_fonts Fonts
|
||||
|
||||
Here you describe your custom fonts.
|
||||
|
||||
- The font menu let you choose a font family installed on your system.
|
||||
- The alt control let you insert alternative font families if the main font is not available. You can insert more than one
|
||||
by using a comma as separator.
|
||||
|
||||
With the + button you add a new font and with the - button you remove the selected font.
|
||||
|
||||
<div style="clear:both"></div>
|
||||
<hr/>
|
||||
|
||||
@section ui_editor_custom_view_creation Creating Custom Views
|
||||
|
||||
If you need to create custom views, you can implement the VSTGUI::VST3EditorDelegate interface in your edit controller class.
|
||||
The createCustomView method will be called if you set the 'custom-view-name' attribute in one of the views.
|
||||
|
||||
Another way to use your own views is to register them at runtime with the UIViewFactory. This method requires more work but has the advantage
|
||||
that the view will be listed like the built-in views and changing attributes work on the fly. See \ref VSTGUI::IViewCreator.
|
||||
|
||||
<hr/>
|
||||
|
||||
@section ui_editor_sub_controllers Sub-Controllers
|
||||
|
||||
Sub-Controllers are useful if you need finer control of your views.
|
||||
You can define sub-controllers for views with the 'sub-controller' attribute.
|
||||
Sub-Controllers will be created via the VSTGUI::VST3EditorDelegate interface.
|
||||
The Sub-Controller object is now owned by the view and will be destroyed when the view is destroyed.
|
||||
|
||||
TODO: describe nested subcontrollers
|
||||
|
||||
The VSTGUI::DelegationController is a helper class if you don't want to control every aspect of the views by forwarding every call to its parent controller.
|
||||
You only overwrite the methods you need in your inherited class.
|
||||
|
||||
If you want to be notified about value changes for controls in your sub-controller but don't want to loose the
|
||||
@ref ui_editor_parameter_binding you can add your sub-controller as dependent of the control:
|
||||
|
||||
@code
|
||||
class MyController : public DelegationController, public CBaseObject
|
||||
{
|
||||
public:
|
||||
MyController (IController* baseController) : DelegationController (baseController), controlView (nullptr) {}
|
||||
~MyController ()
|
||||
{
|
||||
if (controlView)
|
||||
{
|
||||
controlView->unregisterControlListener (this);
|
||||
controlView->forget ();
|
||||
}
|
||||
}
|
||||
|
||||
CView* verifyView (CView* view, const UIAttributes& attributes, IUIDescription* description) override
|
||||
{
|
||||
auto* control = dynamic_cast<CControl*> (view);
|
||||
if (control && control->getTag () == 20)
|
||||
{
|
||||
controlView = control;
|
||||
controlView->registerControlListener (this);
|
||||
controlView->remember ();
|
||||
}
|
||||
return controller->verifyView (view, attributes, description);
|
||||
}
|
||||
|
||||
void valueChanged (CControl* pControl) override
|
||||
{
|
||||
if (pControl == controlView)
|
||||
{
|
||||
// value of the control view changed, do whatever you like
|
||||
}
|
||||
DelegationController::valueChanged (pControl);
|
||||
}
|
||||
|
||||
protected:
|
||||
CControl* controlView;
|
||||
};
|
||||
@endcode
|
||||
|
||||
<hr/>
|
||||
|
||||
@section ui_editor_templates Templates
|
||||
|
||||
Templates are root views where you can group controls in logical entities.
|
||||
You can embed templates into other templates.
|
||||
|
||||
Some views like the VSTGUI::UIViewSwitchContainer shows different templates depending on a control value.
|
||||
|
||||
<hr/>
|
||||
|
||||
*/
|
||||
@@ -0,0 +1,73 @@
|
||||
// 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"
|
||||
|
||||
#if VSTGUI_LIVE_EDITING
|
||||
#include "../../lib/cfont.h"
|
||||
|
||||
namespace VSTGUI {
|
||||
class UIAttributes;
|
||||
struct FocusDrawingSettings;
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class IAction
|
||||
{
|
||||
public:
|
||||
virtual ~IAction () {}
|
||||
|
||||
virtual UTF8StringPtr getName () = 0;
|
||||
virtual void perform () = 0;
|
||||
virtual void undo () = 0;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class IActionPerformer
|
||||
{
|
||||
public:
|
||||
virtual ~IActionPerformer () {}
|
||||
virtual void performAction (IAction* action) = 0;
|
||||
|
||||
virtual void performColorChange (UTF8StringPtr colorName, const CColor& newColor, bool remove = false) = 0;
|
||||
virtual void performTagChange (UTF8StringPtr tagName, UTF8StringPtr tagString, bool remove = false) = 0;
|
||||
virtual void performBitmapChange (UTF8StringPtr bitmapName, UTF8StringPtr bitmapPath, bool remove = false) = 0;
|
||||
virtual void performGradientChange (UTF8StringPtr gradientName, CGradient* newGradient, bool remove = false) = 0;
|
||||
virtual void performFontChange (UTF8StringPtr fontName, CFontRef newFont, bool remove = false) = 0;
|
||||
|
||||
virtual void performColorNameChange (UTF8StringPtr oldName, UTF8StringPtr newName) = 0;
|
||||
virtual void performTagNameChange (UTF8StringPtr oldName, UTF8StringPtr newName) = 0;
|
||||
virtual void performFontNameChange (UTF8StringPtr oldName, UTF8StringPtr newName) = 0;
|
||||
virtual void performBitmapNameChange (UTF8StringPtr oldName, UTF8StringPtr newName) = 0;
|
||||
virtual void performGradientNameChange (UTF8StringPtr oldName, UTF8StringPtr newName) = 0;
|
||||
|
||||
virtual void performAlternativeFontChange (UTF8StringPtr fontName, UTF8StringPtr newAlternativeFonts) = 0;
|
||||
|
||||
virtual void performBitmapMultiFrameChange (UTF8StringPtr bitmapName,
|
||||
const CMultiFrameBitmapDescription* desc) = 0;
|
||||
virtual void performBitmapNinePartTiledChange (UTF8StringPtr bitmapName, const CRect* offsets) = 0;
|
||||
virtual void performBitmapFiltersChange (UTF8StringPtr bitmapName, const std::list<SharedPointer<UIAttributes> >& filterDescription) = 0;
|
||||
|
||||
virtual void beginLiveColorChange (UTF8StringPtr colorName) = 0;
|
||||
virtual void performLiveColorChange (UTF8StringPtr colorName, const CColor& newColor) = 0;
|
||||
virtual void endLiveColorChange (UTF8StringPtr colorName) = 0;
|
||||
|
||||
virtual void performTemplateNameChange (UTF8StringPtr oldName, UTF8StringPtr newName) = 0;
|
||||
virtual void performTemplateMinMaxSizeChange (UTF8StringPtr templateName, CPoint minSize, CPoint maxSize) = 0;
|
||||
virtual void performCreateNewTemplate (UTF8StringPtr name, UTF8StringPtr baseViewClassName) = 0;
|
||||
virtual void performDeleteTemplate (UTF8StringPtr name) = 0;
|
||||
virtual void performDuplicateTemplate (UTF8StringPtr name, UTF8StringPtr dupName) = 0;
|
||||
virtual void onTemplateCreation (UTF8StringPtr name, CView* view) = 0;
|
||||
virtual void onTemplateNameChange (UTF8StringPtr oldName, UTF8StringPtr newName) = 0;
|
||||
|
||||
virtual void performChangeFocusDrawingSettings (const FocusDrawingSettings& newSettings) = 0;
|
||||
|
||||
virtual void beginGroupAction (UTF8StringPtr name) = 0;
|
||||
virtual void finishGroupAction () = 0;
|
||||
};
|
||||
|
||||
} // VSTGUI
|
||||
|
||||
#endif // VSTGUI_LIVE_EDITING
|
||||
@@ -0,0 +1,22 @@
|
||||
// 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_LIVE_EDITING
|
||||
|
||||
namespace VSTGUI {
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class IGridProcessor : virtual public IReference
|
||||
{
|
||||
public:
|
||||
virtual void process (CPoint& p) = 0;
|
||||
};
|
||||
|
||||
} // VSTGUI
|
||||
|
||||
#endif // VSTGUI_LIVE_EDITING
|
||||
|
After Width: | Height: | Size: 842 B |
|
After Width: | Height: | Size: 848 B |
|
After Width: | Height: | Size: 838 B |
|
After Width: | Height: | Size: 835 B |
|
After Width: | Height: | Size: 847 B |
|
After Width: | Height: | Size: 851 B |
|
After Width: | Height: | Size: 848 B |
|
After Width: | Height: | Size: 844 B |
|
After Width: | Height: | Size: 855 B |
|
After Width: | Height: | Size: 870 B |
|
After Width: | Height: | Size: 853 B |
|
After Width: | Height: | Size: 844 B |
|
After Width: | Height: | Size: 842 B |
|
After Width: | Height: | Size: 848 B |
|
After Width: | Height: | Size: 839 B |
|
After Width: | Height: | Size: 837 B |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 708 B |
|
After Width: | Height: | Size: 715 B |
|
After Width: | Height: | Size: 691 B |
|
After Width: | Height: | Size: 679 B |
|
After Width: | Height: | Size: 721 B |
|
After Width: | Height: | Size: 751 B |
|
After Width: | Height: | Size: 704 B |
|
After Width: | Height: | Size: 685 B |
|
After Width: | Height: | Size: 686 B |
|
After Width: | Height: | Size: 686 B |
|
After Width: | Height: | Size: 672 B |
|
After Width: | Height: | Size: 668 B |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 770 B |
|
After Width: | Height: | Size: 680 B |
|
After Width: | Height: | Size: 533 B |
|
After Width: | Height: | Size: 947 B |
|
After Width: | Height: | Size: 593 B |
|
After Width: | Height: | Size: 417 B |
|
After Width: | Height: | Size: 258 B |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 613 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 617 B |
|
After Width: | Height: | Size: 675 B |
|
After Width: | Height: | Size: 309 B |
|
After Width: | Height: | Size: 492 B |
|
After Width: | Height: | Size: 398 B |
|
After Width: | Height: | Size: 860 B |
|
After Width: | Height: | Size: 490 B |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
@@ -0,0 +1,623 @@
|
||||
// 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 "iaction.h"
|
||||
|
||||
#if VSTGUI_LIVE_EDITING
|
||||
|
||||
#include "uiselection.h"
|
||||
#include "../iviewfactory.h"
|
||||
#include "../iuidescription.h"
|
||||
#include "../../lib/ccolor.h"
|
||||
#include "../../lib/cgradient.h"
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
|
||||
namespace VSTGUI {
|
||||
class UIViewFactory;
|
||||
class IUIDescription;
|
||||
class UIDescription;
|
||||
class CViewContainer;
|
||||
class CView;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class Action : public IAction
|
||||
{
|
||||
public:
|
||||
using Func = std::function<void ()>;
|
||||
Action (const std::string& name, Func&& perform, Func&& undo)
|
||||
: name (name), performAction (std::move (perform)), undoAction (std::move (undo))
|
||||
{
|
||||
}
|
||||
|
||||
UTF8StringPtr getName () override { return name.data (); }
|
||||
|
||||
void perform () override { performAction (); }
|
||||
void undo () override { undoAction (); }
|
||||
|
||||
private:
|
||||
std::string name;
|
||||
Func performAction;
|
||||
Func undoAction;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T>
|
||||
class BaseSelectionOperation : public IAction, protected std::list<T>
|
||||
{
|
||||
public:
|
||||
BaseSelectionOperation (UISelection* selection) : selection (selection) {}
|
||||
|
||||
protected:
|
||||
SharedPointer<UISelection> selection;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class SizeToFitOperation : public BaseSelectionOperation<std::pair<SharedPointer<CView>, CRect> >
|
||||
{
|
||||
public:
|
||||
SizeToFitOperation (UISelection* selection);
|
||||
~SizeToFitOperation () override = default;
|
||||
|
||||
UTF8StringPtr getName () override;
|
||||
|
||||
void perform () override;
|
||||
void undo () override;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class UnembedViewOperation : public BaseSelectionOperation<SharedPointer<CView> >
|
||||
{
|
||||
public:
|
||||
UnembedViewOperation (UISelection* selection, const IViewFactory* factory);
|
||||
~UnembedViewOperation () override = default;
|
||||
|
||||
UTF8StringPtr getName () override;
|
||||
|
||||
void perform () override;
|
||||
void undo () override;
|
||||
|
||||
protected:
|
||||
void collectSubviews (CViewContainer* container, bool deep);
|
||||
const IViewFactory* factory;
|
||||
SharedPointer<CViewContainer> containerView;
|
||||
CViewContainer* parent;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class EmbedViewOperation : public BaseSelectionOperation<std::pair<SharedPointer<CView>, CRect> >
|
||||
{
|
||||
public:
|
||||
EmbedViewOperation (UISelection* selection, CViewContainer* newContainer);
|
||||
~EmbedViewOperation () override = default;
|
||||
|
||||
UTF8StringPtr getName () override;
|
||||
void perform () override;
|
||||
void undo () override;
|
||||
|
||||
protected:
|
||||
SharedPointer<CViewContainer> newContainer;
|
||||
CViewContainer* parent;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class ViewCopyOperation : public IAction, protected std::list<SharedPointer<CView> >
|
||||
{
|
||||
public:
|
||||
ViewCopyOperation (UISelection* copySelection, UISelection* workingSelection, CViewContainer* parent, const CPoint& offset, IUIDescription* desc);
|
||||
~ViewCopyOperation () override = default;
|
||||
|
||||
UTF8StringPtr getName () override;
|
||||
void perform () override;
|
||||
void undo () override;
|
||||
protected:
|
||||
SharedPointer<CViewContainer> parent;
|
||||
SharedPointer<UISelection> copySelection;
|
||||
SharedPointer<UISelection> workingSelection;
|
||||
std::list<SharedPointer<CView> > oldSelectedViews;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class ViewSizeChangeOperation : public BaseSelectionOperation<std::pair<SharedPointer<CView>, CRect> >
|
||||
{
|
||||
public:
|
||||
ViewSizeChangeOperation (UISelection* selection, bool sizing, bool autosizingEnabled);
|
||||
~ViewSizeChangeOperation () override = default;
|
||||
|
||||
UTF8StringPtr getName () override;
|
||||
void perform () override;
|
||||
void undo () override;
|
||||
|
||||
bool didChange ();
|
||||
protected:
|
||||
bool first;
|
||||
bool sizing;
|
||||
bool autosizing;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
struct DeleteOperationViewAndNext
|
||||
{
|
||||
DeleteOperationViewAndNext (CView* view, CView* nextView) : view (view), nextView (nextView) {}
|
||||
DeleteOperationViewAndNext (const DeleteOperationViewAndNext& copy) : view (copy.view), nextView (copy.nextView) {}
|
||||
SharedPointer<CView> view;
|
||||
SharedPointer<CView> nextView;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class DeleteOperation : public IAction, protected std::multimap<SharedPointer<CViewContainer>, DeleteOperationViewAndNext>
|
||||
{
|
||||
public:
|
||||
DeleteOperation (UISelection* selection);
|
||||
~DeleteOperation () override = default;
|
||||
|
||||
UTF8StringPtr getName () override;
|
||||
void perform () override;
|
||||
void undo () override;
|
||||
protected:
|
||||
SharedPointer<UISelection> selection;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class InsertViewOperation : public IAction
|
||||
{
|
||||
public:
|
||||
InsertViewOperation (CViewContainer* parent, CView* view, UISelection* selection);
|
||||
~InsertViewOperation () override = default;
|
||||
|
||||
UTF8StringPtr getName () override;
|
||||
void perform () override;
|
||||
void undo () override;
|
||||
protected:
|
||||
SharedPointer<CViewContainer> parent;
|
||||
SharedPointer<CView> view;
|
||||
SharedPointer<UISelection> selection;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class TransformViewTypeOperation : public IAction
|
||||
{
|
||||
public:
|
||||
TransformViewTypeOperation (UISelection* selection, CView* view, IdStringPtr viewClassName,
|
||||
UIDescription* desc, const IViewFactory* factory);
|
||||
~TransformViewTypeOperation () override;
|
||||
|
||||
UTF8StringPtr getName () override;
|
||||
|
||||
void exchangeSubViews (CViewContainer* src, CViewContainer* dst);
|
||||
void perform () override;
|
||||
void undo () override;
|
||||
protected:
|
||||
SharedPointer<CView> view;
|
||||
CView* newView;
|
||||
int32_t insertIndex;
|
||||
SharedPointer<CViewContainer> parent;
|
||||
SharedPointer<UISelection> selection;
|
||||
const IViewFactory* factory;
|
||||
SharedPointer<UIDescription> description;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class AttributeChangeAction : public IAction, protected std::map<SharedPointer<CView>, std::string>
|
||||
{
|
||||
public:
|
||||
AttributeChangeAction (UIDescription* desc, UISelection* selection, const std::string& attrName, const std::string& attrValue);
|
||||
~AttributeChangeAction () override = default;
|
||||
|
||||
UTF8StringPtr getName () override;
|
||||
void perform () override;
|
||||
void undo () override;
|
||||
protected:
|
||||
void updateSelection ();
|
||||
|
||||
UIDescription* desc;
|
||||
SharedPointer<UISelection> selection;
|
||||
std::string attrName;
|
||||
std::string attrValue;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class MultipleAttributeChangeAction : public IAction, public std::vector<std::pair<SharedPointer<CView>, std::string> >
|
||||
{
|
||||
public:
|
||||
MultipleAttributeChangeAction (UIDescription* description, const std::list<CView*>& views, IViewCreator::AttrType attrType, UTF8StringPtr oldValue, UTF8StringPtr newValue);
|
||||
UTF8StringPtr getName () override { return "multiple view attribute changes"; }
|
||||
void perform () override;
|
||||
void undo () override;
|
||||
protected:
|
||||
void setAttributeValue (UTF8StringPtr value);
|
||||
static void collectAllSubViews (CView* view, std::list<CView*>& views);
|
||||
void collectViewsWithAttributeValue (const IViewFactory* viewFactory, IUIDescription* desc,
|
||||
CView* startView, IViewCreator::AttrType type,
|
||||
const std::string& value);
|
||||
|
||||
SharedPointer<UIDescription> description;
|
||||
std::string oldValue;
|
||||
std::string newValue;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class TagChangeAction : public IAction
|
||||
{
|
||||
public:
|
||||
TagChangeAction (UIDescription* description, UTF8StringPtr name, UTF8StringPtr newTagString, bool remove, bool performOrUndo);
|
||||
|
||||
UTF8StringPtr getName () override;
|
||||
void perform () override;
|
||||
void undo () override;
|
||||
|
||||
bool isAddTag () const { return isNewTag; }
|
||||
protected:
|
||||
SharedPointer<UIDescription> description;
|
||||
std::string name;
|
||||
std::string newTag;
|
||||
std::string originalTag;
|
||||
bool remove;
|
||||
bool performOrUndo;
|
||||
bool isNewTag;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class TagNameChangeAction : public IAction
|
||||
{
|
||||
public:
|
||||
TagNameChangeAction (UIDescription* description, UTF8StringPtr oldName, UTF8StringPtr newName, bool performOrUndo);
|
||||
|
||||
UTF8StringPtr getName () override;
|
||||
void perform () override;
|
||||
void undo () override;
|
||||
protected:
|
||||
SharedPointer<UIDescription> description;
|
||||
std::string oldName;
|
||||
std::string newName;
|
||||
bool performOrUndo;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class ColorChangeAction : public IAction
|
||||
{
|
||||
public:
|
||||
ColorChangeAction (UIDescription* description, UTF8StringPtr name, const CColor& color, bool remove, bool performOrUndo);
|
||||
|
||||
UTF8StringPtr getName () override;
|
||||
void perform () override;
|
||||
void undo () override;
|
||||
|
||||
bool isAddColor () const { return isNewColor; }
|
||||
protected:
|
||||
SharedPointer<UIDescription> description;
|
||||
std::string name;
|
||||
CColor newColor;
|
||||
CColor oldColor;
|
||||
bool remove;
|
||||
bool performOrUndo;
|
||||
bool isNewColor;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class ColorNameChangeAction : public IAction
|
||||
{
|
||||
public:
|
||||
ColorNameChangeAction (UIDescription* description, UTF8StringPtr oldName, UTF8StringPtr newName, bool performOrUndo);
|
||||
|
||||
UTF8StringPtr getName () override;
|
||||
void perform () override;
|
||||
void undo () override;
|
||||
protected:
|
||||
SharedPointer<UIDescription> description;
|
||||
std::string oldName;
|
||||
std::string newName;
|
||||
bool performOrUndo;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class BitmapChangeAction : public IAction
|
||||
{
|
||||
public:
|
||||
BitmapChangeAction (UIDescription* description, UTF8StringPtr name, UTF8StringPtr path, bool remove, bool performOrUndo);
|
||||
|
||||
UTF8StringPtr getName () override;
|
||||
void perform () override;
|
||||
void undo () override;
|
||||
|
||||
bool isAddBitmap () const { return isNewBitmap; }
|
||||
protected:
|
||||
SharedPointer<UIDescription> description;
|
||||
std::string name;
|
||||
std::string path;
|
||||
std::string originalPath;
|
||||
bool remove;
|
||||
bool performOrUndo;
|
||||
bool isNewBitmap;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class BitmapNameChangeAction : public IAction
|
||||
{
|
||||
public:
|
||||
BitmapNameChangeAction (UIDescription* description, UTF8StringPtr oldName, UTF8StringPtr newName, bool performOrUndo);
|
||||
|
||||
UTF8StringPtr getName () override;
|
||||
void perform () override;
|
||||
void undo () override;
|
||||
protected:
|
||||
SharedPointer<UIDescription> description;
|
||||
std::string oldName;
|
||||
std::string newName;
|
||||
bool performOrUndo;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class NinePartTiledBitmapChangeAction : public IAction
|
||||
{
|
||||
public:
|
||||
NinePartTiledBitmapChangeAction (UIDescription* description, UTF8StringPtr name, const CRect* rect, bool performOrUndo);
|
||||
~NinePartTiledBitmapChangeAction () override;
|
||||
|
||||
UTF8StringPtr getName () override;
|
||||
void perform () override;
|
||||
void undo () override;
|
||||
protected:
|
||||
SharedPointer<UIDescription> description;
|
||||
std::string name;
|
||||
CRect* oldRect;
|
||||
CRect* newRect;
|
||||
bool performOrUndo;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class MultiFrameBitmapChangeAction : public IAction
|
||||
{
|
||||
public:
|
||||
MultiFrameBitmapChangeAction (UIDescription* description, UTF8StringPtr name,
|
||||
const CMultiFrameBitmapDescription* desc, bool performOrUndo);
|
||||
~MultiFrameBitmapChangeAction () override;
|
||||
|
||||
UTF8StringPtr getName () override;
|
||||
void perform () override;
|
||||
void undo () override;
|
||||
|
||||
protected:
|
||||
SharedPointer<UIDescription> description;
|
||||
std::string name;
|
||||
std::unique_ptr<CMultiFrameBitmapDescription> oldDesc;
|
||||
std::unique_ptr<CMultiFrameBitmapDescription> newDesc;
|
||||
bool performOrUndo;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class BitmapFilterChangeAction : public IAction
|
||||
{
|
||||
public:
|
||||
BitmapFilterChangeAction (UIDescription* description, UTF8StringPtr bitmapName, const std::list<SharedPointer<UIAttributes> >& attributes, bool performOrUndo);
|
||||
~BitmapFilterChangeAction () override = default;
|
||||
|
||||
UTF8StringPtr getName () override;
|
||||
void perform () override;
|
||||
void undo () override;
|
||||
protected:
|
||||
SharedPointer<UIDescription> description;
|
||||
std::string bitmapName;
|
||||
std::list<SharedPointer<UIAttributes> > newAttributes;
|
||||
std::list<SharedPointer<UIAttributes> > oldAttributes;
|
||||
bool performOrUndo;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class GradientChangeAction : public IAction
|
||||
{
|
||||
public:
|
||||
GradientChangeAction (UIDescription* description, UTF8StringPtr name, CGradient* gradient, bool remove, bool performOrUndo);
|
||||
|
||||
UTF8StringPtr getName () override;
|
||||
void perform () override;
|
||||
void undo () override;
|
||||
|
||||
bool isAddGradient () const { return originalGradient == 0; }
|
||||
protected:
|
||||
SharedPointer<UIDescription> description;
|
||||
std::string name;
|
||||
SharedPointer<CGradient> gradient;
|
||||
SharedPointer<CGradient> originalGradient;
|
||||
bool remove;
|
||||
bool performOrUndo;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class GradientNameChangeAction : public IAction
|
||||
{
|
||||
public:
|
||||
GradientNameChangeAction (UIDescription* description, UTF8StringPtr oldName, UTF8StringPtr newName, bool performOrUndo);
|
||||
|
||||
UTF8StringPtr getName () override;
|
||||
void perform () override;
|
||||
void undo () override;
|
||||
protected:
|
||||
SharedPointer<UIDescription> description;
|
||||
std::string oldName;
|
||||
std::string newName;
|
||||
bool performOrUndo;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class FontChangeAction : public IAction
|
||||
{
|
||||
public:
|
||||
FontChangeAction (UIDescription* description, UTF8StringPtr name, CFontRef font, bool remove, bool performOrUndo);
|
||||
|
||||
UTF8StringPtr getName () override;
|
||||
void perform () override;
|
||||
void undo () override;
|
||||
|
||||
bool isAddFont () const { return originalFont == 0; }
|
||||
protected:
|
||||
SharedPointer<UIDescription> description;
|
||||
std::string name;
|
||||
std::string alternativeNames;
|
||||
SharedPointer<CFontDesc> font;
|
||||
SharedPointer<CFontDesc> originalFont;
|
||||
bool remove;
|
||||
bool performOrUndo;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class FontNameChangeAction : public IAction
|
||||
{
|
||||
public:
|
||||
FontNameChangeAction (UIDescription* description, UTF8StringPtr oldName, UTF8StringPtr newName, bool performOrUndo);
|
||||
|
||||
UTF8StringPtr getName () override;
|
||||
void perform () override;
|
||||
void undo () override;
|
||||
protected:
|
||||
SharedPointer<UIDescription> description;
|
||||
std::string oldName;
|
||||
std::string newName;
|
||||
bool performOrUndo;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class AlternateFontChangeAction : public IAction
|
||||
{
|
||||
public:
|
||||
AlternateFontChangeAction (UIDescription* description, UTF8StringPtr fontName, UTF8StringPtr newAlternateFontNames);
|
||||
UTF8StringPtr getName () override;
|
||||
void perform () override;
|
||||
void undo () override;
|
||||
protected:
|
||||
SharedPointer<UIDescription> description;
|
||||
std::string fontName;
|
||||
std::string newAlternateFontNames;
|
||||
std::string oldAlternateFontNames;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class HierarchyMoveViewOperation : public IAction
|
||||
{
|
||||
public:
|
||||
HierarchyMoveViewOperation (CView* view, UISelection* selection, int32_t dir);
|
||||
~HierarchyMoveViewOperation () override = default;
|
||||
|
||||
UTF8StringPtr getName () override;
|
||||
void perform () override;
|
||||
void undo () override;
|
||||
protected:
|
||||
SharedPointer<CView> view;
|
||||
SharedPointer<CViewContainer> parent;
|
||||
SharedPointer<UISelection> selection;
|
||||
int32_t dir;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class TemplateNameChangeAction : public IAction
|
||||
{
|
||||
public:
|
||||
TemplateNameChangeAction (UIDescription* description, IActionPerformer* actionPerformer, UTF8StringPtr oldName, UTF8StringPtr newName);
|
||||
|
||||
UTF8StringPtr getName () override;
|
||||
void perform () override;
|
||||
void undo () override;
|
||||
protected:
|
||||
SharedPointer<UIDescription> description;
|
||||
IActionPerformer* actionPerformer;
|
||||
std::string oldName;
|
||||
std::string newName;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class CreateNewTemplateAction : public IAction
|
||||
{
|
||||
public:
|
||||
CreateNewTemplateAction (UIDescription* description, IActionPerformer* actionPerformer, UTF8StringPtr name, UTF8StringPtr baseViewClassName);
|
||||
|
||||
UTF8StringPtr getName () override;
|
||||
void perform () override;
|
||||
void undo () override;
|
||||
protected:
|
||||
SharedPointer<UIDescription> description;
|
||||
IActionPerformer* actionPerformer;
|
||||
SharedPointer<CView> view;
|
||||
std::string name;
|
||||
std::string baseViewClassName;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class DuplicateTemplateAction : public IAction
|
||||
{
|
||||
public:
|
||||
DuplicateTemplateAction (UIDescription* description, IActionPerformer* actionPerformer, UTF8StringPtr name, UTF8StringPtr dupName);
|
||||
|
||||
UTF8StringPtr getName () override;
|
||||
void perform () override;
|
||||
void undo () override;
|
||||
protected:
|
||||
SharedPointer<UIDescription> description;
|
||||
IActionPerformer* actionPerformer;
|
||||
SharedPointer<CView> view;
|
||||
std::string name;
|
||||
std::string dupName;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class DeleteTemplateAction : public IAction
|
||||
{
|
||||
public:
|
||||
DeleteTemplateAction (UIDescription* description, IActionPerformer* actionPerformer, CView* view, UTF8StringPtr name);
|
||||
|
||||
UTF8StringPtr getName () override;
|
||||
void perform () override;
|
||||
void undo () override;
|
||||
protected:
|
||||
SharedPointer<UIDescription> description;
|
||||
IActionPerformer* actionPerformer;
|
||||
SharedPointer<CView> view;
|
||||
SharedPointer<UIAttributes> attributes;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class ChangeFocusDrawingAction : public IAction
|
||||
{
|
||||
public:
|
||||
ChangeFocusDrawingAction (UIDescription* description, const FocusDrawingSettings& newSettings);
|
||||
|
||||
UTF8StringPtr getName () override;
|
||||
void perform () override;
|
||||
void undo () override;
|
||||
protected:
|
||||
SharedPointer<UIDescription> description;
|
||||
FocusDrawingSettings oldSettings;
|
||||
FocusDrawingSettings newSettings;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class ChangeTemplateMinMaxAction : public IAction
|
||||
{
|
||||
public:
|
||||
ChangeTemplateMinMaxAction (UIDescription* description, UTF8StringPtr templateName, CPoint minSize, CPoint maxSize);
|
||||
|
||||
UTF8StringPtr getName () override;
|
||||
void perform () override;
|
||||
void undo () override;
|
||||
private:
|
||||
void setMinMaxSize (CPoint minimum, CPoint maximum);
|
||||
|
||||
SharedPointer<UIDescription> description;
|
||||
std::string templateName;
|
||||
CPoint minSize;
|
||||
CPoint maxSize;
|
||||
CPoint oldMinSize;
|
||||
CPoint oldMaxSize;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
} // VSTGUI
|
||||
|
||||
#endif // VSTGUI_LIVE_EDITING
|
||||
@@ -0,0 +1,99 @@
|
||||
// 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 "../uidescription.h"
|
||||
|
||||
#if VSTGUI_LIVE_EDITING
|
||||
|
||||
#include "uiselection.h"
|
||||
#include "../delegationcontroller.h"
|
||||
#include "../iviewcreator.h"
|
||||
#include "../iviewfactory.h"
|
||||
#include "../uidescriptionlistener.h"
|
||||
#include "uiundomanager.h"
|
||||
#include "../../lib/controls/ctextedit.h"
|
||||
#include "../../lib/iviewlistener.h"
|
||||
|
||||
namespace VSTGUI {
|
||||
class CRowColumnView;
|
||||
|
||||
namespace UIAttributeControllers {
|
||||
class Controller;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class UIAttributesController : public NonAtomicReferenceCounted,
|
||||
public DelegationController,
|
||||
public UIDescriptionListenerAdapter,
|
||||
public UISelectionListenerAdapter,
|
||||
public IUIUndoManagerListener,
|
||||
public ViewListenerAdapter
|
||||
{
|
||||
public:
|
||||
UIAttributesController (IController* baseController, UISelection* selection, UIUndoManager* undoManager, UIDescription* description);
|
||||
~UIAttributesController () override;
|
||||
|
||||
void beginLiveAttributeChange (const std::string& name, const std::string& currentValue);
|
||||
void endLiveAttributeChange ();
|
||||
void performAttributeChange (const std::string& name, const std::string& value);
|
||||
protected:
|
||||
using StringList = std::list<std::string>;
|
||||
|
||||
CView* createViewForAttribute (const std::string& attrName);
|
||||
void rebuildAttributesView ();
|
||||
void validateAttributeViews ();
|
||||
CView* createValueViewForAttributeType (const IViewFactory* viewFactory, CView* view,
|
||||
const std::string& attrName,
|
||||
IViewCreator::AttrType attrType);
|
||||
void getConsolidatedAttributeNames (StringList& result, const std::string& filter);
|
||||
|
||||
void valueChanged (CControl* pControl) override;
|
||||
CView* verifyView (CView* view, const UIAttributes& attributes, const IUIDescription* description) override;
|
||||
IController* createSubController (IdStringPtr name, const IUIDescription* description) override;
|
||||
IControlListener* getControlListener (UTF8StringPtr name) override;
|
||||
|
||||
void onUIDescTagChanged (UIDescription* desc) override;
|
||||
void onUIDescColorChanged (UIDescription* desc) override;
|
||||
void onUIDescFontChanged (UIDescription* desc) override;
|
||||
void onUIDescBitmapChanged (UIDescription* desc) override;
|
||||
void onUIDescTemplateChanged (UIDescription* desc) override;
|
||||
void onUIDescGradientChanged (UIDescription* desc) override;
|
||||
|
||||
void selectionDidChange (UISelection* selection) override;
|
||||
void selectionViewsDidChange (UISelection* selection) override;
|
||||
|
||||
void onUndoManagerChange () override;
|
||||
|
||||
void viewWillDelete (CView* view) override;
|
||||
|
||||
SharedPointer<UISelection> selection;
|
||||
SharedPointer<UIUndoManager> undoManager;
|
||||
SharedPointer<UIDescription> editDescription;
|
||||
IAction* liveAction;
|
||||
|
||||
using UIAttributeControllerList = std::list<UIAttributeControllers::Controller*>;
|
||||
UIAttributeControllerList attributeControllers;
|
||||
|
||||
enum {
|
||||
kSearchFieldTag = 100,
|
||||
kViewNameTag = 101
|
||||
};
|
||||
|
||||
SharedPointer<CTextEdit> searchField;
|
||||
CTextLabel* viewNameLabel;
|
||||
CRowColumnView* attributeView;
|
||||
CColor attributeNameColor {kBlackCColor};
|
||||
|
||||
std::string filterString;
|
||||
|
||||
const std::string* currentAttributeName;
|
||||
|
||||
bool rebuildRequested{false};
|
||||
};
|
||||
|
||||
} // VSTGUI
|
||||
|
||||
#endif // VSTGUI_LIVE_EDITING
|
||||
@@ -0,0 +1,304 @@
|
||||
// This file is part of VSTGUI. It is subject to the license terms
|
||||
// in the LICENSE file found in the top-level directory of this
|
||||
// distribution and at http://github.com/steinbergmedia/vstgui/LICENSE
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../iuidescription.h"
|
||||
|
||||
#if VSTGUI_LIVE_EDITING
|
||||
|
||||
#include "../uiattributes.h"
|
||||
#include "../uidescriptionlistener.h"
|
||||
#include "../../lib/cdatabrowser.h"
|
||||
#include "../../lib/genericstringlistdatabrowsersource.h"
|
||||
#include "../../lib/controls/csearchtextedit.h"
|
||||
#include "../../lib/controls/cscrollbar.h"
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
namespace VSTGUI {
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class UIBaseDataSource : public GenericStringListDataBrowserSource, public IControlListener, public UIDescriptionListenerAdapter
|
||||
{
|
||||
public:
|
||||
using StringVector = GenericStringListDataBrowserSource::StringVector;
|
||||
|
||||
UIBaseDataSource (UIDescription* description, IActionPerformer* actionPerformer, GenericStringListDataBrowserSourceSelectionChanged* delegate = nullptr)
|
||||
: GenericStringListDataBrowserSource (0, delegate) , description (description), actionPerformer (actionPerformer)
|
||||
{
|
||||
description->registerListener (this);
|
||||
textInset.x = 4;
|
||||
}
|
||||
|
||||
~UIBaseDataSource () override
|
||||
{
|
||||
description->unregisterListener (this);
|
||||
}
|
||||
|
||||
void setSearchFieldControl (CSearchTextEdit* searchControl)
|
||||
{
|
||||
searchField = searchControl;
|
||||
searchField->setListener (this);
|
||||
}
|
||||
|
||||
virtual bool add ()
|
||||
{
|
||||
if (dataBrowser && actionPerformer)
|
||||
{
|
||||
std::string newName (filterString.empty () ? "New" : filterString.data ());
|
||||
if (createUniqueName (newName))
|
||||
{
|
||||
addItem (newName.data ());
|
||||
int32_t row = selectName (newName.data ());
|
||||
if (row != -1)
|
||||
{
|
||||
dbOnMouseDown (CPoint (0, 0), CButtonState (kLButton|kDoubleClick), row, 0, dataBrowser);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool remove ()
|
||||
{
|
||||
if (dataBrowser && actionPerformer)
|
||||
{
|
||||
int32_t selectedRow = dataBrowser->getSelectedRow ();
|
||||
if (selectedRow != CDataBrowser::kNoSelection)
|
||||
{
|
||||
removeItem (names.at (static_cast<uint32_t> (selectedRow)).data ());
|
||||
dbSelectionChanged (dataBrowser);
|
||||
dataBrowser->setSelectedRow (selectedRow);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void setFilter (const UTF8String& filter)
|
||||
{
|
||||
if (filterString != filter)
|
||||
{
|
||||
filterString = filter;
|
||||
int32_t selectedRow = dataBrowser ? dataBrowser->getSelectedRow () : CDataBrowser::kNoSelection;
|
||||
std::string selectedName;
|
||||
if (selectedRow != CDataBrowser::kNoSelection)
|
||||
selectedName = names.at (static_cast<uint32_t> (selectedRow));
|
||||
update ();
|
||||
if (selectedRow != CDataBrowser::kNoSelection)
|
||||
selectName (selectedName.data ());
|
||||
}
|
||||
}
|
||||
|
||||
virtual int32_t selectName (UTF8StringPtr name)
|
||||
{
|
||||
int32_t index = 0;
|
||||
for (auto& it : names)
|
||||
{
|
||||
if (it == name)
|
||||
{
|
||||
dataBrowser->setSelectedRow (index, true);
|
||||
if (delegate)
|
||||
delegate->dbSelectionChanged (index, this);
|
||||
return index;
|
||||
}
|
||||
++index;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
protected:
|
||||
virtual void getNames (std::list<const std::string*>& names) = 0;
|
||||
virtual bool addItem (UTF8StringPtr name) = 0;
|
||||
virtual bool removeItem (UTF8StringPtr name) = 0;
|
||||
virtual bool performNameChange (UTF8StringPtr oldName, UTF8StringPtr newName) = 0;
|
||||
virtual UTF8StringPtr getDefaultsName () = 0;
|
||||
|
||||
virtual void update ()
|
||||
{
|
||||
if (textEditControl)
|
||||
textEditControl->looseFocus ();
|
||||
names.clear ();
|
||||
std::list<const std::string*> tmpNames;
|
||||
getNames (tmpNames);
|
||||
|
||||
std::string filter = filterString.getString ();
|
||||
std::transform (filter.begin (), filter.end (), filter.begin (), ::tolower);
|
||||
|
||||
for (auto& name : tmpNames)
|
||||
{
|
||||
if (!filter.empty ())
|
||||
{
|
||||
std::string tmp (*name);
|
||||
std::transform (tmp.begin (), tmp.end (), tmp.begin (), ::tolower);
|
||||
if (tmp.find (filter) == std::string::npos)
|
||||
continue;
|
||||
}
|
||||
if (name->find ("~ ") == 0)
|
||||
continue; // don't show static items
|
||||
names.emplace_back (UTF8String (*name));
|
||||
}
|
||||
bool vsbIsVisible = false;
|
||||
if (dataBrowser)
|
||||
{
|
||||
if (auto vsb = dataBrowser->getVerticalScrollbar ())
|
||||
vsbIsVisible = vsb->isVisible ();
|
||||
}
|
||||
setStringList (&names);
|
||||
if (dataBrowser)
|
||||
{
|
||||
if (auto vsb = dataBrowser->getVerticalScrollbar ())
|
||||
{
|
||||
if (vsb->isVisible() != vsbIsVisible)
|
||||
dataBrowser->recalculateLayout ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void beforeUIDescSave (UIDescription* desc) override
|
||||
{
|
||||
saveDefaults ();
|
||||
};
|
||||
|
||||
void onUIDescriptionUpdate ()
|
||||
{
|
||||
int32_t selectedRow = dataBrowser ? dataBrowser->getSelectedRow () : CDataBrowser::kNoSelection;
|
||||
std::string selectedName;
|
||||
if (selectedRow != CDataBrowser::kNoSelection)
|
||||
selectedName = names.at (static_cast<uint32_t> (selectedRow));
|
||||
update ();
|
||||
if (selectedRow != CDataBrowser::kNoSelection)
|
||||
selectName (selectedName.data ());
|
||||
}
|
||||
|
||||
virtual void saveDefaults ()
|
||||
{
|
||||
UTF8StringPtr name = getDefaultsName ();
|
||||
if (name)
|
||||
{
|
||||
auto attributes = description->getCustomAttributes (name, true);
|
||||
if (attributes)
|
||||
{
|
||||
attributes->setAttribute ("FilterString", filterString.getString ());
|
||||
if (dataBrowser)
|
||||
{
|
||||
int32_t selectedRow = dataBrowser->getSelectedRow ();
|
||||
attributes->setIntegerAttribute ("SelectedRow", selectedRow);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void loadDefaults ()
|
||||
{
|
||||
UTF8StringPtr name = getDefaultsName ();
|
||||
if (name)
|
||||
{
|
||||
auto attributes = description->getCustomAttributes (name, true);
|
||||
if (attributes)
|
||||
{
|
||||
const std::string* str = attributes->getAttributeValue ("FilterString");
|
||||
if (str)
|
||||
setFilter (str->data ());
|
||||
if (dataBrowser)
|
||||
{
|
||||
int32_t selectedRow;
|
||||
if (attributes->getIntegerAttribute("SelectedRow", selectedRow))
|
||||
dataBrowser->setSelectedRow (selectedRow, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dbAttached (CDataBrowser* browser) override
|
||||
{
|
||||
GenericStringListDataBrowserSource::dbAttached (browser);
|
||||
update ();
|
||||
loadDefaults ();
|
||||
if (searchField)
|
||||
searchField->setText (filterString);
|
||||
}
|
||||
|
||||
void dbRemoved (CDataBrowser* browser) override
|
||||
{
|
||||
saveDefaults ();
|
||||
GenericStringListDataBrowserSource::dbRemoved (browser);
|
||||
}
|
||||
|
||||
void valueChanged (CControl* control) override
|
||||
{
|
||||
CTextEdit* edit = dynamic_cast<CTextEdit*>(control);
|
||||
if (edit)
|
||||
setFilter (edit->getText ());
|
||||
}
|
||||
|
||||
bool createUniqueName (std::string& name, int32_t count = 0)
|
||||
{
|
||||
std::stringstream str;
|
||||
str << name;
|
||||
if (count)
|
||||
{
|
||||
str << ' ';
|
||||
str << count;
|
||||
}
|
||||
for (auto& it : names)
|
||||
{
|
||||
if (it == str.str ())
|
||||
return createUniqueName (name, count+1);
|
||||
}
|
||||
name = str.str ();
|
||||
return true;
|
||||
}
|
||||
|
||||
CMouseEventResult dbOnMouseDown (const CPoint& where, const CButtonState& buttons, int32_t row, int32_t column, CDataBrowser* browser) override
|
||||
{
|
||||
if (buttons.isLeftButton () && buttons.isDoubleClick ())
|
||||
{
|
||||
browser->beginTextEdit (CDataBrowser::Cell (row, column), names.at (static_cast<uint32_t> (row)).data ());
|
||||
}
|
||||
return kMouseDownEventHandledButDontNeedMovedOrUpEvents;
|
||||
}
|
||||
|
||||
void dbCellTextChanged (int32_t _row, int32_t column, UTF8StringPtr newText, CDataBrowser* browser) override
|
||||
{
|
||||
textEditControl = nullptr;
|
||||
if (_row < 0 || _row >= static_cast<int32_t> (names.size ()))
|
||||
return;
|
||||
auto row = static_cast<size_t> (_row);
|
||||
for (auto& name : names)
|
||||
{
|
||||
if (name == newText)
|
||||
return;
|
||||
}
|
||||
auto& currentName = names.at (row);
|
||||
if (performNameChange (currentName.data (), newText))
|
||||
{
|
||||
if (selectName (newText) == -1 && row < names.size ())
|
||||
selectName (names.at (row).data ());
|
||||
}
|
||||
}
|
||||
|
||||
void dbCellSetupTextEdit (int32_t row, int32_t column, CTextEdit* control, CDataBrowser* browser) override
|
||||
{
|
||||
textEditControl = control;
|
||||
textEditControl->setBackColor (kWhiteCColor);
|
||||
textEditControl->setFontColor (fontColor);
|
||||
textEditControl->setFont (drawFont);
|
||||
textEditControl->setHoriAlign (textAlignment);
|
||||
textEditControl->setTextInset (textInset);
|
||||
}
|
||||
|
||||
SharedPointer<UIDescription> description;
|
||||
SharedPointer<CSearchTextEdit> searchField;
|
||||
SharedPointer<CTextEdit> textEditControl;
|
||||
IActionPerformer* actionPerformer;
|
||||
|
||||
StringVector names;
|
||||
UTF8String filterString;
|
||||
};
|
||||
|
||||
} // VSTGUI
|
||||
|
||||
#endif // VSTGUI_LIVE_EDITING
|
||||
@@ -0,0 +1,64 @@
|
||||
// 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 "../uidescription.h"
|
||||
|
||||
#if VSTGUI_LIVE_EDITING
|
||||
|
||||
#include "uiselection.h"
|
||||
#include "uiundomanager.h"
|
||||
#include "iaction.h"
|
||||
#include "../delegationcontroller.h"
|
||||
#include "../../lib/cdatabrowser.h"
|
||||
#include "../../lib/genericstringlistdatabrowsersource.h"
|
||||
|
||||
namespace VSTGUI {
|
||||
class UIBitmapsDataSource;
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class UIBitmapsController : public NonAtomicReferenceCounted,
|
||||
public DelegationController,
|
||||
public GenericStringListDataBrowserSourceSelectionChanged
|
||||
{
|
||||
public:
|
||||
UIBitmapsController (IController* baseController, UIDescription* description,
|
||||
IActionPerformer* actionPerformer, UIUndoManager* undoManager);
|
||||
~UIBitmapsController () override;
|
||||
|
||||
protected:
|
||||
CView* createView (const UIAttributes& attributes, const IUIDescription* description) override;
|
||||
CView* verifyView (CView* view, const UIAttributes& attributes, const IUIDescription* description) override;
|
||||
IControlListener* getControlListener (UTF8StringPtr name) override;
|
||||
void valueChanged (CControl* pControl) override;
|
||||
|
||||
void dbSelectionChanged (int32_t selectedRow, GenericStringListDataBrowserSource* source) override;
|
||||
void dbRowDoubleClick (int32_t row, GenericStringListDataBrowserSource* source) override;
|
||||
|
||||
void showSettingsDialog ();
|
||||
|
||||
static bool valueToString (float value, char utf8String[256], void* userData);
|
||||
static bool stringToValue (UTF8StringPtr txt, float& result, void* userData);
|
||||
|
||||
SharedPointer<UIDescription> editDescription;
|
||||
IActionPerformer* actionPerformer {nullptr};
|
||||
UIUndoManager* undoManager {nullptr};
|
||||
UIBitmapsDataSource* dataSource {nullptr};
|
||||
SharedPointer<CView> bitmapView;
|
||||
SharedPointer<CTextEdit> bitmapPathEdit;
|
||||
SharedPointer<CControl> settingButton;
|
||||
|
||||
enum {
|
||||
kAddTag = 0,
|
||||
kRemoveTag,
|
||||
kSearchTag,
|
||||
kBitmapPathTag,
|
||||
kSettingsTag
|
||||
};
|
||||
};
|
||||
|
||||
} // VSTGUI
|
||||
|
||||
#endif // VSTGUI_LIVE_EDITING
|
||||
@@ -0,0 +1,155 @@
|
||||
// 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 "uicolor.h"
|
||||
|
||||
#if VSTGUI_LIVE_EDITING
|
||||
|
||||
#include "../../lib/coffscreencontext.h"
|
||||
#include "../../lib/controls/coptionmenu.h"
|
||||
|
||||
namespace VSTGUI {
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
UIColor& UIColor::operator= (const CColor& c)
|
||||
{
|
||||
red = c.red; green = c.green; blue = c.blue; alpha = c.alpha;
|
||||
r = red; g = green; b = blue;
|
||||
updateHSL (kTo);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColor::updateHSL (HSLUpdateDirection direction)
|
||||
{
|
||||
if (direction == kTo)
|
||||
toHSL (hue, saturation, lightness);
|
||||
else
|
||||
{
|
||||
fromHSL (hue, saturation, lightness);
|
||||
r = red; g = green; b = blue;
|
||||
}
|
||||
editChange ();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColor::setHue (double h)
|
||||
{
|
||||
if (hue != h)
|
||||
{
|
||||
hue = h;
|
||||
updateHSL (kFrom);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColor::setSaturation (double s)
|
||||
{
|
||||
if (saturation != s)
|
||||
{
|
||||
saturation = s;
|
||||
updateHSL (kFrom);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColor::setLightness (double l)
|
||||
{
|
||||
if (lightness != l)
|
||||
{
|
||||
lightness = l;
|
||||
updateHSL (kFrom);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColor::setRed (double nr)
|
||||
{
|
||||
if (r != nr)
|
||||
{
|
||||
r = nr;
|
||||
red = static_cast<uint8_t> (nr);
|
||||
updateHSL (kTo);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColor::setGreen (double ng)
|
||||
{
|
||||
if (g != ng)
|
||||
{
|
||||
g = ng;
|
||||
green = static_cast<uint8_t> (ng);
|
||||
updateHSL (kTo);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColor::setBlue (double nb)
|
||||
{
|
||||
if (b != nb)
|
||||
{
|
||||
b = nb;
|
||||
blue = static_cast<uint8_t> (nb);
|
||||
updateHSL (kTo);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColor::setAlpha (double na)
|
||||
{
|
||||
alpha = static_cast<uint8_t> (na);
|
||||
editChange ();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColor::beginEdit ()
|
||||
{
|
||||
forEachListener ([this] (IUIColorListener* l) { l->uiColorBeginEditing (this); });
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColor::endEdit ()
|
||||
{
|
||||
forEachListener ([this] (IUIColorListener* l) { l->uiColorEndEditing (this); });
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColor::editChange ()
|
||||
{
|
||||
forEachListener ([this] (IUIColorListener* l) { l->uiColorChanged (this); });
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
SharedPointer<CBitmap> createColorIcon (CColor color, CPoint colorIconSize)
|
||||
{
|
||||
if (auto context = COffscreenContext::create (colorIconSize))
|
||||
{
|
||||
context->beginDraw ();
|
||||
context->setFillColor (color);
|
||||
context->drawRect (CRect (0, 0, colorIconSize.x, colorIconSize.y), kDrawFilled);
|
||||
context->endDraw ();
|
||||
return context->getBitmap ();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
SharedPointer<COptionMenu> createCSSColorMenu (const std::function<void (CColor)>& callback,
|
||||
CPoint colorIconSize)
|
||||
{
|
||||
auto cssColorMenu = makeOwned<COptionMenu> ();
|
||||
auto cssColors = getCSSNamedColors ();
|
||||
std::for_each (cssColors.begin (), cssColors.end (), [&] (const auto& el) {
|
||||
auto item = new CCommandMenuItem ({std::string (el.name.data (), el.name.size ())});
|
||||
item->setActions ([callback, el] (auto item) { callback (el.color); });
|
||||
item->setIcon (createColorIcon (el.color, colorIconSize));
|
||||
cssColorMenu->addEntry (item);
|
||||
});
|
||||
return cssColorMenu;
|
||||
}
|
||||
|
||||
} // VSTGUI
|
||||
|
||||
#endif // VSTGUI_LIVE_EDITING
|
||||
@@ -0,0 +1,95 @@
|
||||
// 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_LIVE_EDITING
|
||||
|
||||
#include "../../lib/ccolor.h"
|
||||
#include "../../lib/dispatchlist.h"
|
||||
|
||||
namespace VSTGUI {
|
||||
|
||||
class UIColor;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
SharedPointer<COptionMenu> createCSSColorMenu (const std::function<void (CColor)>& callback,
|
||||
CPoint colorIconSize = {15., 15.});
|
||||
SharedPointer<CBitmap> createColorIcon (CColor color, CPoint colorIconSize = {15., 15.});
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class IUIColorListener
|
||||
{
|
||||
public:
|
||||
virtual ~IUIColorListener () noexcept = default;
|
||||
|
||||
virtual void uiColorChanged (UIColor* c) = 0;
|
||||
virtual void uiColorBeginEditing (UIColor* c) = 0;
|
||||
virtual void uiColorEndEditing (UIColor* c) = 0;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class UIColorListenerAdapter : public IUIColorListener
|
||||
{
|
||||
public:
|
||||
void uiColorChanged (UIColor* c) override {}
|
||||
void uiColorBeginEditing (UIColor* c) override {}
|
||||
void uiColorEndEditing (UIColor* c) override {}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class UIColor : public NonAtomicReferenceCounted,
|
||||
protected ListenerProvider<UIColor, IUIColorListener>,
|
||||
protected CColor
|
||||
{
|
||||
public:
|
||||
UIColor () : CColor (kTransparentCColor), hue (0), saturation (0), lightness (0) {}
|
||||
|
||||
UIColor& operator= (const CColor& c);
|
||||
const CColor& base () const { return *this; }
|
||||
|
||||
double getRed () const { return r; }
|
||||
double getGreen () const { return g; }
|
||||
double getBlue () const { return b; }
|
||||
double getAlpha () const { return alpha; }
|
||||
|
||||
double getHue () const { return hue; }
|
||||
double getSaturation () const { return saturation; }
|
||||
double getLightness () const { return lightness; }
|
||||
|
||||
void setHue (double h);
|
||||
void setSaturation (double s);
|
||||
void setLightness (double l);
|
||||
|
||||
void setRed (double nr);
|
||||
void setGreen (double ng);
|
||||
void setBlue (double nb);
|
||||
void setAlpha (double na);
|
||||
|
||||
void beginEdit ();
|
||||
void endEdit ();
|
||||
|
||||
using ListenerProvider<UIColor, IUIColorListener>::registerListener;
|
||||
using ListenerProvider<UIColor, IUIColorListener>::unregisterListener;
|
||||
using CColor::operator==;
|
||||
using CColor::operator!=;
|
||||
private:
|
||||
enum HSLUpdateDirection
|
||||
{
|
||||
kFrom,
|
||||
kTo
|
||||
};
|
||||
|
||||
void updateHSL (HSLUpdateDirection direction);
|
||||
void editChange ();
|
||||
|
||||
double hue, saturation, lightness;
|
||||
double r, g, b;
|
||||
};
|
||||
|
||||
} // VSTGUI
|
||||
|
||||
#endif // VSTGUI_LIVE_EDITING
|
||||
@@ -0,0 +1,313 @@
|
||||
// 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 "uicolorchoosercontroller.h"
|
||||
|
||||
#if VSTGUI_LIVE_EDITING
|
||||
|
||||
#include "uicolorslider.h"
|
||||
#include "../uiattributes.h"
|
||||
#include "../iuidescription.h"
|
||||
#include "../../lib/dragging.h"
|
||||
#include <sstream>
|
||||
|
||||
namespace VSTGUI {
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class UIColorChooserDropTarget : public NonAtomicReferenceCounted, public DropTargetAdapter
|
||||
{
|
||||
public:
|
||||
UIColorChooserDropTarget (UIColor* color) : color (color) {}
|
||||
DragOperation onDragEnter (DragEventData eventData) override
|
||||
{
|
||||
for (const auto& item : eventData.drag)
|
||||
{
|
||||
if (item.type != IDataPackage::kText)
|
||||
continue;
|
||||
std::string_view text (static_cast<const char*> (item.data), item.dataSize);
|
||||
if (CColor::isColorRepresentation (text))
|
||||
{
|
||||
CColor dragColor;
|
||||
if (dragColor.fromString (text) && *color != dragColor)
|
||||
{
|
||||
colorString = text;
|
||||
return DragOperation::Copy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return DragOperation::None;
|
||||
}
|
||||
DragOperation onDragMove (DragEventData eventData) override
|
||||
{
|
||||
return colorString.empty () ? DragOperation::None : DragOperation::Copy;
|
||||
}
|
||||
void onDragLeave (DragEventData eventData) override { colorString.clear (); }
|
||||
bool onDrop (DragEventData eventData) override
|
||||
{
|
||||
if (!colorString.empty ())
|
||||
{
|
||||
CColor dragColor;
|
||||
if (dragColor.fromString (colorString))
|
||||
{
|
||||
color->beginEdit ();
|
||||
*color = dragColor;
|
||||
color->endEdit ();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
UIColor* color;
|
||||
std::string colorString;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
UIColorChooserController::UIColorChooserController (IController* baseController, UIColor* color)
|
||||
: DelegationController (baseController)
|
||||
, color (color)
|
||||
{
|
||||
color->registerListener (this);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
UIColorChooserController::~UIColorChooserController ()
|
||||
{
|
||||
color->unregisterListener (this);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorChooserController::updateColorSlider (CControl* control)
|
||||
{
|
||||
float value = 0.f;
|
||||
switch (control->getTag ())
|
||||
{
|
||||
case kHueTag:
|
||||
{
|
||||
value = (float)color->getHue ();
|
||||
break;
|
||||
}
|
||||
case kSaturationTag:
|
||||
{
|
||||
value = (float)color->getSaturation ();
|
||||
break;
|
||||
}
|
||||
case kLightnessTag:
|
||||
{
|
||||
value = (float)color->getLightness ();
|
||||
break;
|
||||
}
|
||||
case kRedTag:
|
||||
{
|
||||
value = (float)color->getRed ();
|
||||
break;
|
||||
}
|
||||
case kGreenTag:
|
||||
{
|
||||
value = (float)color->getGreen ();
|
||||
break;
|
||||
}
|
||||
case kBlueTag:
|
||||
{
|
||||
value = (float)color->getBlue ();
|
||||
break;
|
||||
}
|
||||
case kAlphaTag:
|
||||
{
|
||||
value = (float)color->getAlpha ();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
control->setValue (value);
|
||||
control->invalid ();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorChooserController::updateColorSliders ()
|
||||
{
|
||||
for (auto& control : controls)
|
||||
updateColorSlider (control);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorChooserController::uiColorChanged (UIColor* c)
|
||||
{
|
||||
updateColorSliders ();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool UIColorChooserController::valueToString (float value, char utf8String[256], CParamDisplay::ValueToStringUserData* userData)
|
||||
{
|
||||
auto* display = static_cast<CParamDisplay*>(userData);
|
||||
std::stringstream str;
|
||||
switch (display->getTag ())
|
||||
{
|
||||
case kSaturationTag:
|
||||
case kLightnessTag:
|
||||
{
|
||||
str << (uint32_t)(value * 100);
|
||||
str << " %";
|
||||
break;
|
||||
}
|
||||
case kHueTag:
|
||||
{
|
||||
str << (uint32_t)value;
|
||||
str << kDegreeSymbol;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
str << (uint32_t)value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
strncpy (utf8String, str.str ().c_str (), 255);
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool UIColorChooserController::stringToValue (UTF8StringPtr txt, float& result, CTextEdit::StringToValueUserData* userData)
|
||||
{
|
||||
std::locale origLocale;
|
||||
std::locale::global (std::locale::classic ());
|
||||
|
||||
char* endptr = nullptr;
|
||||
result = (float)strtod (txt, &endptr);
|
||||
|
||||
std::locale::global (origLocale);
|
||||
if (endptr != txt)
|
||||
{
|
||||
auto* display = static_cast<CParamDisplay*>(userData);
|
||||
switch (display->getTag ())
|
||||
{
|
||||
case kSaturationTag:
|
||||
case kLightnessTag:
|
||||
{
|
||||
result /= 100.f;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
CView* UIColorChooserController::createView (const UIAttributes& attributes, const IUIDescription* description)
|
||||
{
|
||||
const std::string* name = attributes.getAttributeValue (IUIDescription::kCustomViewName);
|
||||
if (name)
|
||||
{
|
||||
if (*name == "UIColorSlider")
|
||||
{
|
||||
const std::string* controlTagStr = attributes.getAttributeValue ("control-tag");
|
||||
int32_t tag = controlTagStr ? description->getTagForName (controlTagStr->c_str ()) : -1;
|
||||
if (tag != -1)
|
||||
{
|
||||
return new UIColorSlider (color, tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return DelegationController::createView (attributes, description);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
CView* UIColorChooserController::verifyView (CView* view, const UIAttributes& attributes, const IUIDescription* description)
|
||||
{
|
||||
auto* control = dynamic_cast<CControl*>(view);
|
||||
if (control && control->getTag () >= 0)
|
||||
{
|
||||
controls.emplace_back (control);
|
||||
auto* textEdit = dynamic_cast<CTextEdit*> (control);
|
||||
if (textEdit)
|
||||
{
|
||||
textEdit->setValueToStringFunction (valueToString);
|
||||
textEdit->setStringToValueFunction (stringToValue);
|
||||
}
|
||||
updateColorSlider (control);
|
||||
}
|
||||
else if (auto container = view->asViewContainer ())
|
||||
{
|
||||
container->setDropTarget (makeOwned<UIColorChooserDropTarget> (color));
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
IControlListener* UIColorChooserController::getControlListener (UTF8StringPtr name)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorChooserController::controlBeginEdit (CControl* pControl)
|
||||
{
|
||||
if (pControl->getTag () >= kHueTag && pControl->getTag () <= kAlphaTag)
|
||||
{
|
||||
color->beginEdit ();
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorChooserController::controlEndEdit (CControl* pControl)
|
||||
{
|
||||
if (pControl->getTag () >= kHueTag && pControl->getTag () <= kAlphaTag)
|
||||
{
|
||||
color->endEdit ();
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorChooserController::valueChanged (CControl* pControl)
|
||||
{
|
||||
switch (pControl->getTag ())
|
||||
{
|
||||
case kHueTag:
|
||||
{
|
||||
color->setHue (pControl->getValue ());
|
||||
break;
|
||||
}
|
||||
case kSaturationTag:
|
||||
{
|
||||
color->setSaturation (pControl->getValue ());
|
||||
break;
|
||||
}
|
||||
case kLightnessTag:
|
||||
{
|
||||
color->setLightness (pControl->getValue ());
|
||||
break;
|
||||
}
|
||||
case kRedTag:
|
||||
{
|
||||
color->setRed (pControl->getValue ());
|
||||
break;
|
||||
}
|
||||
case kGreenTag:
|
||||
{
|
||||
color->setGreen (pControl->getValue ());
|
||||
break;
|
||||
}
|
||||
case kBlueTag:
|
||||
{
|
||||
color->setBlue (pControl->getValue ());
|
||||
break;
|
||||
}
|
||||
case kAlphaTag:
|
||||
{
|
||||
color->setAlpha (pControl->getValue ());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // VSTGUI
|
||||
|
||||
#endif // VSTGUI_LIVE_EDITING
|
||||
@@ -0,0 +1,61 @@
|
||||
// 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_LIVE_EDITING
|
||||
|
||||
#include "uicolor.h"
|
||||
#include "../delegationcontroller.h"
|
||||
#include "../../lib/controls/ctextedit.h"
|
||||
|
||||
namespace VSTGUI {
|
||||
class UIColor;
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class UIColorChooserController : public NonAtomicReferenceCounted,
|
||||
public DelegationController,
|
||||
public UIColorListenerAdapter
|
||||
{
|
||||
public:
|
||||
UIColorChooserController (IController* baseController, UIColor* color);
|
||||
~UIColorChooserController () override;
|
||||
|
||||
protected:
|
||||
CView* createView (const UIAttributes& attributes, const IUIDescription* description) override;
|
||||
CView* verifyView (CView* view, const UIAttributes& attributes, const IUIDescription* description) override;
|
||||
IControlListener* getControlListener (UTF8StringPtr name) override;
|
||||
void valueChanged (CControl* pControl) override;
|
||||
void controlBeginEdit (CControl* pControl) override;
|
||||
void controlEndEdit (CControl* pControl) override;
|
||||
|
||||
void updateColorSlider (CControl* control);
|
||||
void updateColorSliders ();
|
||||
|
||||
void uiColorChanged (UIColor* c) override;
|
||||
|
||||
static bool valueToString (float value, char utf8String[256], CParamDisplay::ValueToStringUserData* userData);
|
||||
static bool stringToValue (UTF8StringPtr txt, float& result, CTextEdit::StringToValueUserData* userData);
|
||||
|
||||
SharedPointer<UIColor> color;
|
||||
using ControlList = std::list<SharedPointer<CControl>>;
|
||||
ControlList controls;
|
||||
|
||||
enum {
|
||||
kHueTag = 0,
|
||||
kSaturationTag,
|
||||
kLightnessTag,
|
||||
kRedTag,
|
||||
kGreenTag,
|
||||
kBlueTag,
|
||||
kAlphaTag,
|
||||
kNumTags
|
||||
};
|
||||
};
|
||||
|
||||
} // VSTGUI
|
||||
|
||||
#endif // VSTGUI_LIVE_EDITING
|
||||
@@ -0,0 +1,505 @@
|
||||
// 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 "uicolorscontroller.h"
|
||||
|
||||
#if VSTGUI_LIVE_EDITING
|
||||
|
||||
#include "uicolor.h"
|
||||
#include "uicolorchoosercontroller.h"
|
||||
#include "uieditcontroller.h"
|
||||
#include "uibasedatasource.h"
|
||||
#include "../../lib/ccolor.h"
|
||||
#include "../../lib/cdropsource.h"
|
||||
#include "../../lib/coffscreencontext.h"
|
||||
#include "../../lib/dragging.h"
|
||||
#include "../../lib/optional.h"
|
||||
#include "../../lib/idatapackage.h"
|
||||
#include "../../lib/controls/coptionmenu.h"
|
||||
#include "../../lib/controls/csearchtextedit.h"
|
||||
|
||||
namespace VSTGUI {
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class UIColorsDataSource : public UIBaseDataSource, public UIColorListenerAdapter
|
||||
{
|
||||
public:
|
||||
UIColorsDataSource (UIDescription* description, IActionPerformer* actionPerformer, UIColor* color);
|
||||
~UIColorsDataSource () override;
|
||||
|
||||
protected:
|
||||
void onUIDescColorChanged (UIDescription* desc) override;
|
||||
void update () override;
|
||||
void getNames (std::list<const std::string*>& names) override;
|
||||
bool addItem (UTF8StringPtr name) override;
|
||||
bool removeItem (UTF8StringPtr name) override;
|
||||
bool performNameChange (UTF8StringPtr oldName, UTF8StringPtr newName) override;
|
||||
UTF8StringPtr getDefaultsName () override { return "UIColorsDataSource"; }
|
||||
|
||||
void dbDrawCell (CDrawContext* context, const CRect& size, int32_t row, int32_t column, int32_t flags, CDataBrowser* browser) override;
|
||||
void dbCellSetupTextEdit (int32_t row, int32_t column, CTextEdit* control, CDataBrowser* browser) override;
|
||||
void dbSelectionChanged (CDataBrowser* browser) override;
|
||||
|
||||
void dbOnDragEnterBrowser (IDataPackage* drag, CDataBrowser* browser) override;
|
||||
void dbOnDragExitBrowser (IDataPackage* drag, CDataBrowser* browser) override;
|
||||
DragOperation dbOnDragEnterCell (int32_t row, int32_t column, const CPoint& where, IDataPackage* drag, CDataBrowser* browser) override;
|
||||
DragOperation dbOnDragMoveInCell (int32_t row, int32_t column, const CPoint& where, IDataPackage* drag, CDataBrowser* browser) override;
|
||||
void dbOnDragExitCell (int32_t row, int32_t column, IDataPackage* drag, CDataBrowser* browser) override;
|
||||
bool dbOnDropInCell (int32_t row, int32_t column, const CPoint& where, IDataPackage* drag, CDataBrowser* browser) override;
|
||||
CMouseEventResult dbOnMouseDown (const CPoint& where, const CButtonState& buttons, int32_t row, int32_t column, CDataBrowser* browser) override;
|
||||
CMouseEventResult dbOnMouseMoved (const CPoint& where, const CButtonState& buttons, int32_t row, int32_t column, CDataBrowser* browser) override;
|
||||
CMouseEventResult dbOnMouseUp (const CPoint& where, const CButtonState& buttons, int32_t row,
|
||||
int32_t column, CDataBrowser* browser) override;
|
||||
|
||||
CCoord getColorIconWith ();
|
||||
|
||||
void uiColorChanged (UIColor* c) override;
|
||||
void uiColorBeginEditing (UIColor* c) override;
|
||||
void uiColorEndEditing (UIColor* c) override;
|
||||
|
||||
SharedPointer<UIColor> color;
|
||||
bool editing;
|
||||
Optional<CColor> dragColor;
|
||||
int32_t dragRow;
|
||||
DragStartMouseObserver dragStartMouseObserver;
|
||||
bool allowDrag {false};
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
UIColorsDataSource::UIColorsDataSource (UIDescription* description, IActionPerformer* actionPerformer, UIColor* color)
|
||||
: UIBaseDataSource (description, actionPerformer)
|
||||
, color (color)
|
||||
, editing (false)
|
||||
, dragRow (-1)
|
||||
{
|
||||
color->registerListener (this);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
UIColorsDataSource::~UIColorsDataSource ()
|
||||
{
|
||||
color->unregisterListener (this);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorsDataSource::onUIDescColorChanged (UIDescription* desc)
|
||||
{
|
||||
onUIDescriptionUpdate ();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorsDataSource::uiColorChanged (UIColor* c)
|
||||
{
|
||||
if (editing)
|
||||
{
|
||||
int32_t selectedRow = dataBrowser->getSelectedRow ();
|
||||
if (selectedRow != CDataBrowser::kNoSelection)
|
||||
{
|
||||
actionPerformer->performLiveColorChange (
|
||||
names.at (static_cast<uint32_t> (selectedRow)).data (), color->base ());
|
||||
dataBrowser->setSelectedRow (selectedRow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorsDataSource::uiColorBeginEditing (UIColor* c)
|
||||
{
|
||||
int32_t selectedRow = dataBrowser->getSelectedRow ();
|
||||
if (selectedRow != CDataBrowser::kNoSelection)
|
||||
{
|
||||
actionPerformer->beginLiveColorChange (
|
||||
names.at (static_cast<uint32_t> (selectedRow)).data ());
|
||||
editing = true;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorsDataSource::uiColorEndEditing (UIColor* c)
|
||||
{
|
||||
int32_t selectedRow = dataBrowser->getSelectedRow ();
|
||||
if (selectedRow != CDataBrowser::kNoSelection)
|
||||
{
|
||||
actionPerformer->endLiveColorChange (
|
||||
names.at (static_cast<uint32_t> (selectedRow)).data ());
|
||||
editing = false;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorsDataSource::getNames (std::list<const std::string*>& names)
|
||||
{
|
||||
description->collectColorNames (names);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool UIColorsDataSource::addItem (UTF8StringPtr name)
|
||||
{
|
||||
actionPerformer->performColorChange (name, kWhiteCColor);
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool UIColorsDataSource::removeItem (UTF8StringPtr name)
|
||||
{
|
||||
actionPerformer->performColorChange (name, kWhiteCColor, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorsDataSource::update ()
|
||||
{
|
||||
UIBaseDataSource::update ();
|
||||
if (dataBrowser)
|
||||
{
|
||||
dbSelectionChanged (dataBrowser);
|
||||
dataBrowser->invalid ();
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorsDataSource::dbSelectionChanged (CDataBrowser* browser)
|
||||
{
|
||||
int32_t selectedRow = dataBrowser->getSelectedRow ();
|
||||
if (selectedRow != CDataBrowser::kNoSelection)
|
||||
{
|
||||
CColor c;
|
||||
if (description->getColor (names.at (static_cast<uint32_t> (selectedRow)).data (), c))
|
||||
{
|
||||
if (c != color->base ())
|
||||
{
|
||||
*color = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
CCoord UIColorsDataSource::getColorIconWith ()
|
||||
{
|
||||
return dataBrowser ? dbGetRowHeight (dataBrowser) : 0.;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorsDataSource::dbDrawCell (CDrawContext* context, const CRect& size, int32_t row, int32_t column, int32_t flags, CDataBrowser* browser)
|
||||
{
|
||||
GenericStringListDataBrowserSource::drawRowBackground (context, size, row, flags, browser);
|
||||
CRect r (size);
|
||||
r.right -= getColorIconWith ();
|
||||
GenericStringListDataBrowserSource::drawRowString (context, r, row, flags, browser);
|
||||
CColor cellColor;
|
||||
if (description->getColor (names.at (static_cast<uint32_t> (row)).data (), cellColor))
|
||||
{
|
||||
context->setFillColor (cellColor);
|
||||
context->setFrameColor (dragRow == row ? kRedCColor : kBlackCColor);
|
||||
context->setLineWidth (context->getHairlineSize ());
|
||||
context->setLineStyle (kLineSolid);
|
||||
context->setDrawMode (kAliasing);
|
||||
r = size;
|
||||
r.left = r.right - getColorIconWith ();
|
||||
r.inset (2, 2);
|
||||
context->drawRect (r, kDrawFilledAndStroked);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorsDataSource::dbCellSetupTextEdit (int32_t row, int32_t column, CTextEdit* control, CDataBrowser* browser)
|
||||
{
|
||||
UIBaseDataSource::dbCellSetupTextEdit(row, column, control, browser);
|
||||
CRect r (control->getViewSize ());
|
||||
r.right -= getColorIconWith ();
|
||||
control->setViewSize (r);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
CMouseEventResult UIColorsDataSource::dbOnMouseDown (const CPoint& where,
|
||||
const CButtonState& buttons, int32_t row,
|
||||
int32_t column, CDataBrowser* browser)
|
||||
{
|
||||
auto r = browser->getCellBounds ({row, column});
|
||||
r.left = r.right - getColorIconWith ();
|
||||
r.inset (2, 2);
|
||||
if (r.pointInside (where))
|
||||
{
|
||||
allowDrag = true;
|
||||
dragStartMouseObserver.init (where);
|
||||
}
|
||||
UIBaseDataSource::dbOnMouseDown (where, buttons, row, column, browser);
|
||||
return kMouseEventHandled;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
CMouseEventResult UIColorsDataSource::dbOnMouseMoved (const CPoint& where,
|
||||
const CButtonState& buttons, int32_t row,
|
||||
int32_t column, CDataBrowser* browser)
|
||||
{
|
||||
if (row < 0 || column < 0)
|
||||
return UIBaseDataSource::dbOnMouseMoved (where, buttons, row, column, browser);
|
||||
|
||||
auto r = browser->getCellBounds ({row, column});
|
||||
r.left = r.right - getColorIconWith ();
|
||||
r.inset (2, 2);
|
||||
if (allowDrag)
|
||||
{
|
||||
if (buttons.isLeftButton ())
|
||||
{
|
||||
if (dragStartMouseObserver.shouldStartDrag (where))
|
||||
{
|
||||
CColor cellColor;
|
||||
if (description->getColor (names.at (static_cast<uint32_t> (row)).data (), cellColor))
|
||||
{
|
||||
auto colorStr = cellColor.toString ();
|
||||
auto dropSource = CDropSource::create (
|
||||
colorStr.data (), static_cast<uint32_t> (colorStr.length () + 1),
|
||||
CDropSource::kText);
|
||||
SharedPointer<CBitmap> dragBitmap;
|
||||
if (auto offscreen = COffscreenContext::create (r.getSize ()))
|
||||
{
|
||||
offscreen->beginDraw ();
|
||||
offscreen->setFillColor (cellColor);
|
||||
offscreen->drawRect (CRect (0, 0, r.getWidth(), r.getHeight()), kDrawFilled);
|
||||
offscreen->endDraw();
|
||||
dragBitmap = offscreen->getBitmap ();
|
||||
}
|
||||
|
||||
auto df = makeOwned<DragCallbackFunctions> ();
|
||||
df->endedFunc = [browser, Self = shared (this)] (IDraggingSession*, CPoint,
|
||||
DragOperation) {
|
||||
browser->getFrame ()->setCursor (kCursorDefault);
|
||||
Self->allowDrag = false;
|
||||
};
|
||||
browser->doDrag (DragDescription (dropSource, -r.getSize () / 2., dragBitmap), df);
|
||||
}
|
||||
}
|
||||
return kMouseEventHandled;
|
||||
}
|
||||
}
|
||||
if (r.pointInside (where))
|
||||
browser->getFrame ()->setCursor (kCursorMovableObject);
|
||||
else
|
||||
browser->getFrame ()->setCursor (kCursorDefault);
|
||||
return UIBaseDataSource::dbOnMouseMoved (where, buttons, row, column, browser);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
CMouseEventResult UIColorsDataSource::dbOnMouseUp (const CPoint& where, const CButtonState& buttons,
|
||||
int32_t row, int32_t column,
|
||||
CDataBrowser* browser)
|
||||
{
|
||||
allowDrag = false;
|
||||
return UIBaseDataSource::dbOnMouseUp (where, buttons, row, column, browser);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool UIColorsDataSource::performNameChange (UTF8StringPtr oldName, UTF8StringPtr newName)
|
||||
{
|
||||
actionPerformer->performColorNameChange (oldName, newName);
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorsDataSource::dbOnDragEnterBrowser (IDataPackage* drag, CDataBrowser* browser)
|
||||
{
|
||||
for (const auto& item : drag)
|
||||
{
|
||||
if (item.type != IDataPackage::kText)
|
||||
continue;
|
||||
std::string_view text (static_cast<const char*> (item.data), item.dataSize);
|
||||
if (CColor::isColorRepresentation (text))
|
||||
{
|
||||
CColor c;
|
||||
c.fromString (text);
|
||||
dragColor = Optional<CColor> (c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorsDataSource::dbOnDragExitBrowser (IDataPackage* drag, CDataBrowser* browser)
|
||||
{
|
||||
dragColor = {};
|
||||
dragRow = -1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
DragOperation UIColorsDataSource::dbOnDragEnterCell (int32_t row, int32_t column, const CPoint& where, IDataPackage* drag, CDataBrowser* browser)
|
||||
{
|
||||
if (dragColor && row >= 0)
|
||||
{
|
||||
CColor cellColor;
|
||||
if (description->getColor (names.at (static_cast<uint32_t> (row)).data (), cellColor) &&
|
||||
cellColor != *dragColor)
|
||||
{
|
||||
dragRow = row;
|
||||
browser->invalidateRow (dragRow);
|
||||
return DragOperation::Copy;
|
||||
}
|
||||
else
|
||||
dragRow = -1;
|
||||
}
|
||||
return DragOperation::None;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
DragOperation UIColorsDataSource::dbOnDragMoveInCell (int32_t row, int32_t column, const CPoint& where, IDataPackage* drag, CDataBrowser* browser)
|
||||
{
|
||||
return (dragColor && (dragRow >= 0 || row == -1)) ? DragOperation::Copy : DragOperation::None;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorsDataSource::dbOnDragExitCell (int32_t row, int32_t column, IDataPackage* drag, CDataBrowser* browser)
|
||||
{
|
||||
if (dragColor)
|
||||
{
|
||||
if (dragRow >= 0)
|
||||
browser->invalidateRow (dragRow);
|
||||
dragRow = -1;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool UIColorsDataSource::dbOnDropInCell (int32_t row, int32_t column, const CPoint& where, IDataPackage* drag, CDataBrowser* browser)
|
||||
{
|
||||
if (dragColor)
|
||||
{
|
||||
if (row >= 0)
|
||||
{
|
||||
CColor cellColor;
|
||||
if (description->getColor (names.at (static_cast<uint32_t> (row)).data (), cellColor))
|
||||
{
|
||||
if (cellColor != *dragColor)
|
||||
{
|
||||
actionPerformer->performColorChange (names[static_cast<uint32_t> (row)].data (), *dragColor);
|
||||
selectName (names[static_cast<uint32_t> (row)].data ());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string newName (filterString.empty () ? "New" : filterString.data ());
|
||||
if (createUniqueName (newName))
|
||||
{
|
||||
actionPerformer->performColorChange (newName.data (), *dragColor);
|
||||
selectName (newName.data ());
|
||||
}
|
||||
}
|
||||
dragColor = {};
|
||||
dragRow = -1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
UIColorsController::UIColorsController (IController* baseController, UIDescription* description, IActionPerformer* actionPerformer)
|
||||
: DelegationController (baseController)
|
||||
, editDescription (description)
|
||||
, actionPerformer (actionPerformer)
|
||||
, dataSource (nullptr)
|
||||
, color (makeOwned<UIColor> ())
|
||||
{
|
||||
dataSource = new UIColorsDataSource (editDescription, actionPerformer, color);
|
||||
UIEditController::setupDataSource (dataSource);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
UIColorsController::~UIColorsController ()
|
||||
{
|
||||
dataSource->forget ();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
CView* UIColorsController::createView (const UIAttributes& attributes, const IUIDescription* description)
|
||||
{
|
||||
const std::string* name = attributes.getAttributeValue (IUIDescription::kCustomViewName);
|
||||
if (name)
|
||||
{
|
||||
if (*name == "ColorsBrowser")
|
||||
{
|
||||
CDataBrowser* dataBrowser = new CDataBrowser (CRect (0, 0, 0, 0), dataSource, CDataBrowser::kDrawRowLines|CScrollView::kHorizontalScrollbar|CScrollView::kVerticalScrollbar);
|
||||
return dataBrowser;
|
||||
}
|
||||
}
|
||||
return DelegationController::createView (attributes, description);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
CView* UIColorsController::verifyView (CView* view, const UIAttributes& attributes, const IUIDescription* description)
|
||||
{
|
||||
auto searchField = dynamic_cast<CSearchTextEdit*>(view);
|
||||
if (searchField && searchField->getTag () == kSearchTag)
|
||||
{
|
||||
dataSource->setSearchFieldControl (searchField);
|
||||
return searchField;
|
||||
}
|
||||
return controller->verifyView (view, attributes, description);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
IControlListener* UIColorsController::getControlListener (UTF8StringPtr name)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorsController::valueChanged (CControl* pControl)
|
||||
{
|
||||
switch (pControl->getTag ())
|
||||
{
|
||||
case kAddTag:
|
||||
{
|
||||
if (pControl->getValue () == pControl->getMax ())
|
||||
{
|
||||
dataSource->add ();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kRemoveTag:
|
||||
{
|
||||
if (pControl->getValue () == pControl->getMax ())
|
||||
{
|
||||
dataSource->remove ();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
IController* UIColorsController::createSubController (IdStringPtr name, const IUIDescription* description)
|
||||
{
|
||||
if (std::strcmp (name, "ColorChooserController") == 0)
|
||||
return new UIColorChooserController (this, color);
|
||||
return controller->createSubController (name, description);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorsController::appendContextMenuItems (COptionMenu& contextMenu, CView* view,
|
||||
const CPoint& where)
|
||||
{
|
||||
auto item = new CCommandMenuItem ({"Add Color"});
|
||||
item->setActions ([this] (auto) { dataSource->add (); });
|
||||
contextMenu.addEntry (item);
|
||||
item = new CCommandMenuItem ({"Remove Color"});
|
||||
item->setActions ([this] (auto) { dataSource->remove (); });
|
||||
contextMenu.addEntry (item);
|
||||
contextMenu.addSeparator ();
|
||||
|
||||
auto cssColorMenu = createCSSColorMenu ([this] (auto newColor) {
|
||||
if (color)
|
||||
{
|
||||
color->beginEdit ();
|
||||
*color = newColor;
|
||||
color->endEdit ();
|
||||
}
|
||||
});
|
||||
contextMenu.addEntry (cssColorMenu, "Set to CSS Color");
|
||||
}
|
||||
|
||||
} // VSTGUI
|
||||
|
||||
#endif // VSTGUI_LIVE_EDITING
|
||||
@@ -0,0 +1,53 @@
|
||||
// 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 "../uidescription.h"
|
||||
|
||||
#if VSTGUI_LIVE_EDITING
|
||||
|
||||
#include "../delegationcontroller.h"
|
||||
#include "uiselection.h"
|
||||
#include "uiundomanager.h"
|
||||
#include "iaction.h"
|
||||
|
||||
namespace VSTGUI {
|
||||
class UIColorsDataSource;
|
||||
class UIColor;
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class UIColorsController : public NonAtomicReferenceCounted,
|
||||
public DelegationController,
|
||||
public IContextMenuController2
|
||||
{
|
||||
public:
|
||||
UIColorsController (IController* baseController, UIDescription* description, IActionPerformer* actionPerformer);
|
||||
~UIColorsController () override;
|
||||
|
||||
protected:
|
||||
CView* createView (const UIAttributes& attributes, const IUIDescription* description) override;
|
||||
CView* verifyView (CView* view, const UIAttributes& attributes, const IUIDescription* description) override;
|
||||
IControlListener* getControlListener (UTF8StringPtr name) override;
|
||||
void valueChanged (CControl* pControl) override;
|
||||
IController* createSubController (IdStringPtr name, const IUIDescription* description) override;
|
||||
|
||||
void appendContextMenuItems (COptionMenu& contextMenu, CView* view,
|
||||
const CPoint& where) override;
|
||||
|
||||
SharedPointer<UIDescription> editDescription;
|
||||
IActionPerformer* actionPerformer;
|
||||
UIColorsDataSource* dataSource;
|
||||
SharedPointer<UIColor> color;
|
||||
|
||||
enum {
|
||||
kAddTag = 0,
|
||||
kRemoveTag,
|
||||
kSearchTag
|
||||
};
|
||||
};
|
||||
|
||||
} // VSTGUI
|
||||
|
||||
#endif // VSTGUI_LIVE_EDITING
|
||||
@@ -0,0 +1,167 @@
|
||||
// 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 "uicolorslider.h"
|
||||
|
||||
#if VSTGUI_LIVE_EDITING
|
||||
|
||||
#include "../../lib/coffscreencontext.h"
|
||||
|
||||
namespace VSTGUI {
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
UIColorSlider::UIColorSlider (UIColor* color, int32_t style)
|
||||
: CSlider (CRect (0, 0, 0, 0), nullptr, 0, 0, 0, nullptr, nullptr)
|
||||
, color (color)
|
||||
, style (style)
|
||||
{
|
||||
color->registerListener (this);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
UIColorSlider::~UIColorSlider ()
|
||||
{
|
||||
color->unregisterListener (this);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorSlider::draw (CDrawContext* context)
|
||||
{
|
||||
if (getHandle () == nullptr)
|
||||
updateHandle (context);
|
||||
if (getBackground () == nullptr)
|
||||
updateBackground (context);
|
||||
CSlider::draw (context);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorSlider::setViewSize (const CRect& rect, bool invalid)
|
||||
{
|
||||
bool widthDifferent = rect.getWidth () != getWidth ();
|
||||
bool heightDifferent = rect.getHeight () != getHeight ();
|
||||
CSlider::setViewSize (rect, invalid);
|
||||
if (widthDifferent)
|
||||
setBackground (nullptr);
|
||||
if (heightDifferent)
|
||||
setHandle (nullptr);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorSlider::uiColorChanged (UIColor* c)
|
||||
{
|
||||
setBackground (nullptr);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorSlider::updateBackground (CDrawContext* context)
|
||||
{
|
||||
double scaleFactor = context->getScaleFactor ();
|
||||
if (auto offscreen = COffscreenContext::create ({getWidth (), getHeight ()}, scaleFactor))
|
||||
{
|
||||
const int32_t kNumPoints = (style <= kLightness) ? 360 : 256;
|
||||
CCoord width = std::floor (getWidth () + 0.5);
|
||||
offscreen->beginDraw ();
|
||||
offscreen->setDrawMode (kAliasing);
|
||||
CCoord minWidth = 1. / scaleFactor;
|
||||
CCoord widthPerColor = width / static_cast<double> (kNumPoints - 1);
|
||||
CRect r;
|
||||
r.setHeight (getHeight ());
|
||||
r.setWidth (widthPerColor < minWidth ? minWidth : (std::floor (widthPerColor * scaleFactor + 0.5) / scaleFactor));
|
||||
r.offset (-r.getWidth (), 0);
|
||||
offscreen->setLineWidth (minWidth);
|
||||
|
||||
auto maxLines = static_cast<size_t> (std::ceil (widthPerColor / minWidth));
|
||||
CDrawContext::LineList lines;
|
||||
lines.reserve (maxLines);
|
||||
|
||||
for (int32_t i = 0; i < kNumPoints; i++)
|
||||
{
|
||||
CCoord x = std::floor (widthPerColor * i * scaleFactor + 0.5) / scaleFactor;
|
||||
if (x > r.right || i == kNumPoints -1)
|
||||
{
|
||||
CColor c = color->base ();
|
||||
switch (style)
|
||||
{
|
||||
case kRed:
|
||||
{
|
||||
c.red = (uint8_t)i;
|
||||
break;
|
||||
}
|
||||
case kGreen:
|
||||
{
|
||||
c.green = (uint8_t)i;
|
||||
break;
|
||||
}
|
||||
case kBlue:
|
||||
{
|
||||
c.blue = (uint8_t)i;
|
||||
break;
|
||||
}
|
||||
case kAlpha:
|
||||
{
|
||||
c.alpha = (uint8_t)i;
|
||||
break;
|
||||
}
|
||||
case kHue:
|
||||
{
|
||||
double hue = (static_cast<double> (i) / static_cast<double> (kNumPoints)) * 360.;
|
||||
c.fromHSL (hue, color->getSaturation (), color->getLightness ());
|
||||
break;
|
||||
}
|
||||
case kSaturation:
|
||||
{
|
||||
double sat = (static_cast<double> (i) / static_cast<double> (kNumPoints));
|
||||
c.fromHSL (color->getHue (), sat, color->getLightness ());
|
||||
break;
|
||||
}
|
||||
case kLightness:
|
||||
{
|
||||
double light = (static_cast<double> (i) / static_cast<double> (kNumPoints));
|
||||
c.fromHSL (color->getHue (), color->getSaturation (), light);
|
||||
break;
|
||||
}
|
||||
}
|
||||
offscreen->setFrameColor (c);
|
||||
CCoord next = r.left + widthPerColor;
|
||||
while (r.left < next)
|
||||
{
|
||||
lines.emplace_back (r.getTopLeft (), r.getBottomLeft ());
|
||||
r.offset (minWidth, 0);
|
||||
}
|
||||
if (!lines.empty ())
|
||||
{
|
||||
offscreen->drawLines (lines);
|
||||
lines.clear ();
|
||||
}
|
||||
}
|
||||
}
|
||||
offscreen->drawLine (r.getTopLeft (), r.getBottomLeft ());
|
||||
offscreen->endDraw ();
|
||||
setBackground (offscreen->getBitmap ());
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorSlider::updateHandle (CDrawContext* context)
|
||||
{
|
||||
if (auto offscreen = COffscreenContext::create ({7., getHeight ()}, context->getScaleFactor ()))
|
||||
{
|
||||
auto lineWidth = 1.;
|
||||
offscreen->beginDraw ();
|
||||
offscreen->setFrameColor (kBlackCColor);
|
||||
offscreen->setLineWidth (lineWidth);
|
||||
offscreen->setDrawMode (kAliasing);
|
||||
CRect r (0, 0, 7, getHeight ());
|
||||
offscreen->drawRect (r, kDrawStroked);
|
||||
r.inset (lineWidth, lineWidth);
|
||||
offscreen->setFrameColor (kWhiteCColor);
|
||||
offscreen->drawRect (r, kDrawStroked);
|
||||
offscreen->endDraw ();
|
||||
setHandle (offscreen->getBitmap ());
|
||||
}
|
||||
}
|
||||
|
||||
} // VSTGUI
|
||||
|
||||
#endif // VSTGUI_LIVE_EDITING
|
||||
@@ -0,0 +1,51 @@
|
||||
// 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_LIVE_EDITING
|
||||
|
||||
#include "uicolor.h"
|
||||
#include "../../lib/controls/cslider.h"
|
||||
|
||||
namespace VSTGUI {
|
||||
class UIColor;
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class UIColorSlider : public CSlider, public UIColorListenerAdapter
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
kHue,
|
||||
kSaturation,
|
||||
kLightness,
|
||||
kRed,
|
||||
kGreen,
|
||||
kBlue,
|
||||
kAlpha
|
||||
};
|
||||
UIColorSlider (UIColor* color, int32_t style);
|
||||
~UIColorSlider () override;
|
||||
|
||||
protected:
|
||||
void draw (CDrawContext* context) override;
|
||||
void setViewSize (const CRect& rect, bool invalid = true) override;
|
||||
void uiColorChanged (UIColor* c) override;
|
||||
void updateBackground (CDrawContext* context);
|
||||
void updateHandle (CDrawContext* context);
|
||||
|
||||
SharedPointer<UIColor> color;
|
||||
int32_t style;
|
||||
};
|
||||
|
||||
|
||||
} // VSTGUI
|
||||
|
||||
#endif // VSTGUI_LIVE_EDITING
|
||||
@@ -0,0 +1,142 @@
|
||||
// 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 "uicrosslines.h"
|
||||
|
||||
#if VSTGUI_LIVE_EDITING
|
||||
|
||||
#include "../../lib/cviewcontainer.h"
|
||||
#include "../../lib/cdrawcontext.h"
|
||||
#include "uiselection.h"
|
||||
|
||||
namespace VSTGUI {
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
UICrossLines::UICrossLines (CViewContainer* view, int32_t style, const CColor& background, const CColor& foreground)
|
||||
: UIOverlayView (view)
|
||||
, style (style)
|
||||
, background (background)
|
||||
, foreground (foreground)
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
UICrossLines::~UICrossLines ()
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UICrossLines::update (UISelection* selection)
|
||||
{
|
||||
invalid ();
|
||||
|
||||
CPoint p;
|
||||
currentRect = selection->getBounds ();
|
||||
localToFrame (p);
|
||||
currentRect.offset (-p.x, -p.y);
|
||||
|
||||
invalid ();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UICrossLines::update (const CPoint& point)
|
||||
{
|
||||
invalid ();
|
||||
|
||||
currentRect.left = point.x-1;
|
||||
currentRect.top = point.y-1;
|
||||
currentRect.setWidth (1);
|
||||
currentRect.setHeight (1);
|
||||
getTargetView ()->getTransform ().transform (currentRect);
|
||||
CPoint p;
|
||||
getParentView ()->frameToLocal (p);
|
||||
currentRect.offset (p.x, p.y);
|
||||
getTargetView ()->localToFrame (p);
|
||||
currentRect.offset (p.x, p.y);
|
||||
|
||||
invalid ();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UICrossLines::update (const CRect& rect)
|
||||
{
|
||||
invalid ();
|
||||
currentRect = rect;
|
||||
getTargetView ()->getTransform ().transform (currentRect);
|
||||
CPoint p;
|
||||
getParentView ()->frameToLocal (p);
|
||||
currentRect.offset (p.x, p.y);
|
||||
getTargetView ()->localToFrame (p);
|
||||
currentRect.offset (p.x, p.y);
|
||||
invalid ();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UICrossLines::invalid ()
|
||||
{
|
||||
if (style == kLassoStyle)
|
||||
{
|
||||
auto r = currentRect;
|
||||
r.makeIntegral ();
|
||||
if (!r.isEmpty ())
|
||||
invalidRect (r);
|
||||
return;
|
||||
}
|
||||
CRect frameRect = getViewSize ();
|
||||
invalidRect (CRect (currentRect.left-3, frameRect.top, currentRect.left+3, frameRect.bottom));
|
||||
invalidRect (CRect (frameRect.left, currentRect.top-3, frameRect.right, currentRect.top+3));
|
||||
if (style == kSelectionStyle)
|
||||
{
|
||||
invalidRect (CRect (currentRect.right-3, frameRect.top, currentRect.right+3, frameRect.bottom));
|
||||
invalidRect (CRect (frameRect.left, currentRect.bottom-3, frameRect.right, currentRect.bottom+3));
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UICrossLines::drawLines (CDrawContext* pContext, const CRect& size, const CRect& selectionSize)
|
||||
{
|
||||
pContext->drawLine (CPoint (size.left, selectionSize.top), CPoint (size.right, selectionSize.top));
|
||||
pContext->drawLine (CPoint (selectionSize.left, size.top), CPoint (selectionSize.left, size.bottom));
|
||||
if (style == kSelectionStyle)
|
||||
{
|
||||
pContext->drawLine (CPoint (size.left, selectionSize.bottom - 1), CPoint (size.right, selectionSize.bottom - 1));
|
||||
pContext->drawLine (CPoint (selectionSize.right-1, size.top), CPoint (selectionSize.right-1, size.bottom));
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UICrossLines::draw (CDrawContext* pContext)
|
||||
{
|
||||
CRect size = getViewSize ();
|
||||
|
||||
pContext->setDrawMode (kAliasing);
|
||||
pContext->setLineStyle (kLineSolid);
|
||||
pContext->setFrameColor (background);
|
||||
pContext->setLineWidth (1);
|
||||
|
||||
if (style == kLassoStyle)
|
||||
{
|
||||
auto r = currentRect;
|
||||
r.makeIntegral ();
|
||||
if (r.isEmpty ())
|
||||
return;
|
||||
pContext->setFillColor (foreground);
|
||||
pContext->drawRect (r, kDrawFilledAndStroked);
|
||||
return;
|
||||
}
|
||||
|
||||
CRect selectionSize (currentRect);
|
||||
drawLines (pContext, size, selectionSize);
|
||||
|
||||
static const CCoord dashLength [] = {3,3};
|
||||
static const CLineStyle lineStyle (CLineStyle::kLineCapButt, CLineStyle::kLineJoinMiter, 0, 2, dashLength);
|
||||
|
||||
pContext->setLineStyle (lineStyle);
|
||||
pContext->setFrameColor (foreground);
|
||||
drawLines (pContext, size, selectionSize);
|
||||
}
|
||||
|
||||
} // VSTGUI
|
||||
|
||||
#endif // VSTGUI_LIVE_EDITING
|
||||
@@ -0,0 +1,53 @@
|
||||
// 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"
|
||||
|
||||
#if VSTGUI_LIVE_EDITING
|
||||
|
||||
#include "uioverlayview.h"
|
||||
#include "../../lib/crect.h"
|
||||
#include "../../lib/ccolor.h"
|
||||
#include "../../lib/cview.h"
|
||||
#include "../../lib/iviewlistener.h"
|
||||
|
||||
namespace VSTGUI {
|
||||
class UISelection;
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class UICrossLines : public UIOverlayView
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
kSelectionStyle,
|
||||
kDragStyle,
|
||||
kLassoStyle,
|
||||
};
|
||||
|
||||
UICrossLines (CViewContainer* view, int32_t style, const CColor& background = kWhiteCColor, const CColor& foreground = kBlackCColor);
|
||||
~UICrossLines () override;
|
||||
|
||||
int32_t getStyle () const { return style; }
|
||||
|
||||
void update (UISelection* selection);
|
||||
void update (const CPoint& point);
|
||||
void update (const CRect& rect);
|
||||
void invalid () override;
|
||||
void draw (CDrawContext* pContext) override;
|
||||
protected:
|
||||
void drawLines (CDrawContext* pContext, const CRect& size, const CRect& selectionSize);
|
||||
|
||||
CViewContainer* editView;
|
||||
CRect currentRect;
|
||||
int32_t style;
|
||||
|
||||
CColor background;
|
||||
CColor foreground;
|
||||
};
|
||||
|
||||
} // VSTGUI
|
||||
|
||||
#endif // VSTGUI_LIVE_EDITING
|
||||