From 74bddb258369e2b04e74a4c401694d3a6778a07b Mon Sep 17 00:00:00 2001 From: Nicholas Thompson Date: Sat, 2 Jan 2021 10:31:25 -0500 Subject: [PATCH] First pass with clang-format --- .clang-format | 59 ++ blueprint/core/blueprint_AppHarness.cpp | 69 +- blueprint/core/blueprint_AppHarness.h | 10 +- blueprint/core/blueprint_CanvasView.h | 850 ++++++++---------- blueprint/core/blueprint_EcmascriptEngine.cpp | 268 +++--- blueprint/core/blueprint_EcmascriptEngine.h | 32 +- blueprint/core/blueprint_FileWatcher.h | 12 +- blueprint/core/blueprint_GenericEditor.cpp | 38 +- blueprint/core/blueprint_GenericEditor.h | 36 +- blueprint/core/blueprint_ImageView.h | 48 +- blueprint/core/blueprint_RawTextView.h | 11 +- .../core/blueprint_ReactApplicationRoot.cpp | 24 +- .../core/blueprint_ReactApplicationRoot.h | 65 +- blueprint/core/blueprint_ScrollView.cpp | 57 +- blueprint/core/blueprint_ScrollView.h | 31 +- .../blueprint_ScrollViewContentShadowView.h | 6 +- blueprint/core/blueprint_ShadowView.cpp | 157 ++-- blueprint/core/blueprint_ShadowView.h | 164 ++-- blueprint/core/blueprint_TextShadowView.cpp | 9 +- blueprint/core/blueprint_TextShadowView.h | 12 +- blueprint/core/blueprint_TextView.h | 29 +- blueprint/core/blueprint_View.cpp | 120 +-- blueprint/core/blueprint_View.h | 49 +- blueprint/core/blueprint_ViewManager.cpp | 52 +- blueprint/core/blueprint_ViewManager.h | 20 +- 25 files changed, 1131 insertions(+), 1097 deletions(-) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..1c2a7ba5 --- /dev/null +++ b/.clang-format @@ -0,0 +1,59 @@ +--- +AccessModifierOffset: '-4' +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: 'false' +AlignConsecutiveDeclarations: 'false' +AlignEscapedNewlinesLeft: 'false' +AlignOperands: 'true' +AlignTrailingComments: 'false' +AllowAllParametersOfDeclarationOnNextLine: 'false' +AllowShortBlocksOnASingleLine: 'false' +AllowShortCaseLabelsOnASingleLine: 'false' +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: 'false' +AllowShortLoopsOnASingleLine: 'false' +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: 'false' +AlwaysBreakTemplateDeclarations: 'true' +BinPackArguments: 'false' +BinPackParameters: 'false' +BreakAfterJavaFieldAnnotations: 'false' +BreakBeforeBinaryOperators: NonAssignment +BreakBeforeBraces: Allman +BreakBeforeTernaryOperators: 'true' +BreakConstructorInitializersBeforeComma: 'false' +BreakStringLiterals: 'false' +ColumnLimit: '0' +ConstructorInitializerAllOnOneLineOrOnePerLine: 'true' +ConstructorInitializerIndentWidth: '4' +ContinuationIndentWidth: '4' +Cpp11BracedListStyle: 'false' +DerivePointerAlignment: 'false' +DisableFormat: 'false' +ExperimentalAutoDetectBinPacking: 'false' +IndentCaseLabels: 'true' +IndentWidth: '4' +IndentWrappedFunctionNames: 'true' +KeepEmptyLinesAtTheStartOfBlocks: 'false' +Language: Cpp +MaxEmptyLinesToKeep: '1' +NamespaceIndentation: All +PointerAlignment: Left +ReflowComments: 'false' +SortIncludes: 'true' +SpaceAfterCStyleCast: 'true' +SpaceAfterLogicalNot: 'true' +SpaceBeforeAssignmentOperators: 'true' +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: 'false' +SpacesInAngles: 'false' +SpacesInCStyleCastParentheses: 'false' +SpacesInContainerLiterals: 'true' +SpacesInParentheses: 'false' +SpacesInSquareBrackets: 'false' +Standard: Cpp11 +TabWidth: '4' +UseTab: Never + +... diff --git a/blueprint/core/blueprint_AppHarness.cpp b/blueprint/core/blueprint_AppHarness.cpp index a9ba0c8e..895920a2 100644 --- a/blueprint/core/blueprint_AppHarness.cpp +++ b/blueprint/core/blueprint_AppHarness.cpp @@ -11,10 +11,8 @@ #include "blueprint_AppHarness.h" - namespace blueprint { - //============================================================================== AppHarness::AppHarness(ReactApplicationRoot& _appRoot) : appRoot(_appRoot) @@ -25,11 +23,17 @@ namespace blueprint appRoot.reset(); appRoot.bindNativeRenderingHooks(); - if (onBeforeAll) { onBeforeAll(); } + if (onBeforeAll) + { + onBeforeAll(); + } for (const auto& f : fileWatcher->getWatchedFiles()) { - if (onBeforeEach) { onBeforeEach(f); } + if (onBeforeEach) + { + onBeforeEach(f); + } try { @@ -52,22 +56,27 @@ namespace blueprint } } - if (onAfterEach) { onAfterEach(f); } + if (onAfterEach) + { + onAfterEach(f); + } } - if (onAfterAll) { onAfterAll(); } + if (onAfterAll) + { + onAfterAll(); + } }); - } //============================================================================== - void AppHarness::watch (const juce::File& f) + void AppHarness::watch(const juce::File& f) { if (fileWatcher) fileWatcher->watch(f); } - void AppHarness::watch (const std::vector& fs) + void AppHarness::watch(const std::vector& fs) { if (fileWatcher) { @@ -84,11 +93,17 @@ namespace blueprint if (fileWatcher == nullptr) return; - if (onBeforeAll) { onBeforeAll(); } + if (onBeforeAll) + { + onBeforeAll(); + } for (const auto& f : fileWatcher->getWatchedFiles()) { - if (onBeforeEach) { onBeforeEach(f); } + if (onBeforeEach) + { + onBeforeEach(f); + } try { @@ -111,10 +126,16 @@ namespace blueprint } } - if (onAfterEach) { onAfterEach(f); } + if (onAfterEach) + { + onAfterEach(f); + } } - if (onAfterAll) { onAfterAll(); } + if (onAfterAll) + { + onAfterAll(); + } // Finally, kick off the file watch process fileWatcher->start(); @@ -132,16 +153,28 @@ namespace blueprint if (fileWatcher == nullptr) return; - if (onBeforeAll) { onBeforeAll(); } + if (onBeforeAll) + { + onBeforeAll(); + } for (const auto& f : fileWatcher->getWatchedFiles()) { - if (onBeforeEach) { onBeforeEach(f); } + if (onBeforeEach) + { + onBeforeEach(f); + } appRoot.evaluate(f); - if (onAfterEach) { onAfterEach(f); } + if (onAfterEach) + { + onAfterEach(f); + } } - if (onAfterAll) { onAfterAll(); } + if (onAfterAll) + { + onAfterAll(); + } } -} +} // namespace blueprint diff --git a/blueprint/core/blueprint_AppHarness.h b/blueprint/core/blueprint_AppHarness.h index 86762b54..aa4f7c9c 100644 --- a/blueprint/core/blueprint_AppHarness.h +++ b/blueprint/core/blueprint_AppHarness.h @@ -13,10 +13,8 @@ #include "blueprint_FileWatcher.h" #include "blueprint_ReactApplicationRoot.h" - namespace blueprint { - /** The AppHarness is a simple class which composes over your ReactApplicationRoot * to provide file watching and hot reloading behavior for the bundle files your app evaluates. * @@ -37,8 +35,8 @@ namespace blueprint AppHarness(ReactApplicationRoot& _appRoot); //============================================================================== - void watch (const juce::File& f); - void watch (const std::vector& fs); + void watch(const juce::File& f); + void watch(const std::vector& fs); /** Run the initial evaluation step and then watch for file changes. */ void start(); @@ -222,7 +220,7 @@ namespace blueprint std::unique_ptr fileWatcher; //============================================================================== - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AppHarness) + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(AppHarness) }; -} +} // namespace blueprint diff --git a/blueprint/core/blueprint_CanvasView.h b/blueprint/core/blueprint_CanvasView.h index 9891d887..824cea6e 100644 --- a/blueprint/core/blueprint_CanvasView.h +++ b/blueprint/core/blueprint_CanvasView.h @@ -59,22 +59,20 @@ namespace blueprint class CanvasContext : public juce::DynamicObject { public: - using FillStyle = juce::FillType; + using FillStyle = juce::FillType; using StrokeStyle = juce::FillType; struct Properties { - FillStyle fillStyle{}; - StrokeStyle strokeStyle{}; - int lineWidth = 1; - juce::Font font{}; + FillStyle fillStyle{}; + StrokeStyle strokeStyle{}; + int lineWidth = 1; + juce::Font font{}; juce::Justification textAlign = juce::Justification::left; }; explicit CanvasContext() - : ctxWidth(1) - , ctxHeight(1) - , image(juce::Image::ARGB, ctxWidth, ctxHeight, true) + : ctxWidth(1), ctxHeight(1), image(juce::Image::ARGB, ctxWidth, ctxHeight, true) { registerNativeProperties(); registerNativeFunctions(); @@ -89,9 +87,9 @@ namespace blueprint */ void setSize(int width, int height) { - ctxWidth = std::max(width, 1); + ctxWidth = std::max(width, 1); ctxHeight = std::max(height, 1); - image = image.rescaled(ctxWidth, ctxHeight, juce::Graphics::highResamplingQuality); + image = image.rescaled(ctxWidth, ctxHeight, juce::Graphics::highResamplingQuality); } /** Get the juce::Image instance that has been rendered to. This can be drawn to the screen @@ -105,9 +103,9 @@ namespace blueprint /** init should be called before passing the CanvasContext instance to a JS drawing function. */ void init() { - graphics = std::make_unique(image); + graphics = std::make_unique(image); properties = Properties{}; - path = juce::Path{}; + path = juce::Path{}; transformStack.clear(); } @@ -115,47 +113,41 @@ namespace blueprint private: void registerNativeProperties() { - setProperty("__setFillStyle", juce::var::NativeFunction { - [=](const juce::var::NativeFunctionArgs& args) -> juce::var { - jassert(graphics); - jassert(args.numArguments == 1); + setProperty("__setFillStyle", juce::var::NativeFunction{ [=](const juce::var::NativeFunctionArgs& args) -> juce::var { + jassert(graphics); + jassert(args.numArguments == 1); - //TODO: Implement fillStyle pattern - //TODO: Implement fillStyle gradient + //TODO: Implement fillStyle pattern + //TODO: Implement fillStyle gradient - const auto colourHex = args.arguments[0].toString(); - properties.fillStyle.setColour(juce::Colour::fromString(colourHex)); + const auto colourHex = args.arguments[0].toString(); + properties.fillStyle.setColour(juce::Colour::fromString(colourHex)); - return juce::var(); - } - }); + return juce::var(); + } }); - setProperty("__setStrokeStyle", juce::var::NativeFunction { - [=](const juce::var::NativeFunctionArgs& args) -> juce::var { - jassert(graphics); - jassert(args.numArguments == 1); + setProperty("__setStrokeStyle", juce::var::NativeFunction{ [=](const juce::var::NativeFunctionArgs& args) -> juce::var { + jassert(graphics); + jassert(args.numArguments == 1); - //TODO: Implement strokeStyle pattern - //TODO: Implement stokeStyle gradient + //TODO: Implement strokeStyle pattern + //TODO: Implement stokeStyle gradient - const auto colourHex = args.arguments[0].toString(); - properties.strokeStyle.setColour(juce::Colour::fromString(colourHex)); + const auto colourHex = args.arguments[0].toString(); + properties.strokeStyle.setColour(juce::Colour::fromString(colourHex)); - return juce::var(); - } - }); + return juce::var(); + } }); - setProperty("__setLineWidth", juce::var::NativeFunction { - [=](const juce::var::NativeFunctionArgs& args) -> juce::var { - jassert(graphics); - jassert(args.numArguments == 1); + setProperty("__setLineWidth", juce::var::NativeFunction{ [=](const juce::var::NativeFunctionArgs& args) -> juce::var { + jassert(graphics); + jassert(args.numArguments == 1); - const int lineWidth = args.arguments[0]; - properties.lineWidth = lineWidth; + const int lineWidth = args.arguments[0]; + properties.lineWidth = lineWidth; - return juce::var(); - } - }); + return juce::var(); + } }); /** * Currently supports space separated css-font like strings with the below supported format/properties: @@ -184,479 +176,435 @@ namespace blueprint * * 'bold 14px "DejaVu Serif"' * */ - setProperty("__setFont", juce::var::NativeFunction { - [=](const juce::var::NativeFunctionArgs& args) -> juce::var { - jassert(graphics); - jassert(args.numArguments == 1); + setProperty("__setFont", juce::var::NativeFunction{ [=](const juce::var::NativeFunctionArgs& args) -> juce::var { + jassert(graphics); + jassert(args.numArguments == 1); - auto fontString = args.arguments[0].toString(); - auto values = juce::StringArray::fromTokens (fontString, juce::StringRef (" "), {}); + auto fontString = args.arguments[0].toString(); + auto values = juce::StringArray::fromTokens(fontString, juce::StringRef(" "), {}); - jassert(values.size() >=2 && values.size() <= 4); + jassert(values.size() >= 2 && values.size() <= 4); - juce::Font::FontStyleFlags flags = juce::Font::plain; - float fontSize = 0; - juce::String typeface; + juce::Font::FontStyleFlags flags = juce::Font::plain; + float fontSize = 0; + juce::String typeface; - for (auto& value : values) - { - // Remove any quoted values likely used when specifying fonts - value = value.unquoted(); - - if (value == "bold") - { - flags = static_cast(flags | juce::Font::bold); - } - else if (value == "italic") - { - flags = static_cast(flags | juce::Font::italic); - } - else if (value.contains("px")) - { - fontSize = (float)value.getIntValue(); - } - else if (value != "normal") + for (auto& value : values) { - typeface = value; + // Remove any quoted values likely used when specifying fonts + value = value.unquoted(); + + if (value == "bold") + { + flags = static_cast(flags | juce::Font::bold); + } + else if (value == "italic") + { + flags = static_cast(flags | juce::Font::italic); + } + else if (value.contains("px")) + { + fontSize = (float) value.getIntValue(); + } + else if (value != "normal") + { + typeface = value; + } } - } - - properties.font = juce::Font(typeface, fontSize, flags); - - return juce::var(); - } - }); - - setProperty("__setTextAlign", juce::var::NativeFunction { - [=](const juce::var::NativeFunctionArgs& args) -> juce::var { - jassert(graphics); - jassert(args.numArguments == 1); - - const juce::String textAlign = args.arguments[0].toString(); - - //TODO: Have "start" and "end" depend on a "direction" property. - // Leaving with sensible defaults for now. No clear way - // to provide/infer text direction from locale at the moment etc. - if (textAlign == "left") - properties.textAlign = juce::Justification::left; - else if (textAlign == "right") - properties.textAlign = juce::Justification::right; - else if (textAlign == "center") - properties.textAlign = juce::Justification::horizontallyCentred; - else if (textAlign == "start") - properties.textAlign = juce::Justification::left; - else if (textAlign == "end") - properties.textAlign = juce::Justification::right; - - return juce::var(); - } - }); + + properties.font = juce::Font(typeface, fontSize, flags); + + return juce::var(); + } }); + + setProperty("__setTextAlign", juce::var::NativeFunction{ [=](const juce::var::NativeFunctionArgs& args) -> juce::var { + jassert(graphics); + jassert(args.numArguments == 1); + + const juce::String textAlign = args.arguments[0].toString(); + + //TODO: Have "start" and "end" depend on a "direction" property. + // Leaving with sensible defaults for now. No clear way + // to provide/infer text direction from locale at the moment etc. + if (textAlign == "left") + properties.textAlign = juce::Justification::left; + else if (textAlign == "right") + properties.textAlign = juce::Justification::right; + else if (textAlign == "center") + properties.textAlign = juce::Justification::horizontallyCentred; + else if (textAlign == "start") + properties.textAlign = juce::Justification::left; + else if (textAlign == "end") + properties.textAlign = juce::Justification::right; + + return juce::var(); + } }); } void registerNativeFunctions() { -// setProperty("rect", juce::var::NativeFunction { -// [=](const juce::var::NativeFunctionArgs& args) -> juce::var { -// jassert(args.numArguments == 4); -// -// const float x = args.arguments[0]; -// const float y = args.arguments[1]; -// const float width = args.arguments[2]; -// const float height = args.arguments[3]; -// -// // TODO: For some reason this operation closes the current path. -// // The API docs suggest addRectangle should be added as a new sub-path -// // leaving the previous path open. -// // Fix. -// path.addRectangle(x, y, width, height); -// -// return juce::var(); -// } -// }); - - setProperty("fillRect", juce::var::NativeFunction { - [=](const juce::var::NativeFunctionArgs& args) -> juce::var { - jassert(graphics); - jassert(args.numArguments == 4); - - const int x = args.arguments[0]; - const int y = args.arguments[1]; - const int width = args.arguments[2]; - const int height = args.arguments[3]; - - graphics->setFillType(properties.fillStyle); - graphics->fillRect(x, y, width, height); - - return juce::var(); - } - }); - - setProperty("strokeRect", juce::var::NativeFunction { - [=](const juce::var::NativeFunctionArgs& args) -> juce::var { - jassert(graphics); - jassert(args.numArguments == 4); - - const int x = args.arguments[0]; - const int y = args.arguments[1]; - const int width = args.arguments[2]; - const int height = args.arguments[3]; - - graphics->setColour(properties.strokeStyle.colour); - graphics->drawRect(x, y, width, height, properties.lineWidth); - - return juce::var(); - } - }); - - setProperty("strokeRoundedRect", juce::var::NativeFunction { - [=](const juce::var::NativeFunctionArgs& args) -> juce::var { - jassert(graphics); - jassert(args.numArguments == 5); - - const float x = args.arguments[0]; - const float y = args.arguments[1]; - const float width = args.arguments[2]; - const float height = args.arguments[3]; - const float cornerSize = args.arguments[4]; - - graphics->setColour(properties.strokeStyle.colour); - graphics->drawRoundedRectangle(x, y, width, height, cornerSize, (float) properties.lineWidth); - - return juce::var(); - } - }); - - setProperty("fillRoundedRect", juce::var::NativeFunction { - [=](const juce::var::NativeFunctionArgs& args) -> juce::var { - jassert(graphics); - jassert(args.numArguments == 5); - - const float x = args.arguments[0]; - const float y = args.arguments[1]; - const float width = args.arguments[2]; - const float height = args.arguments[3]; - const float cornerSize = args.arguments[4]; - - graphics->setFillType(properties.fillStyle); - graphics->fillRoundedRectangle(x, y, width, height, cornerSize); - - return juce::var(); - } - }); - - setProperty("clearRect", juce::var::NativeFunction { - [=](const juce::var::NativeFunctionArgs& args) -> juce::var { - jassert(graphics); - jassert(args.numArguments == 4); - - const int x = args.arguments[0]; - const int y = args.arguments[1]; - const int width = args.arguments[2]; - const int height = args.arguments[3]; - - juce::Rectangle area (x, y, width, height); - image.clear(area); - - return juce::var(); - } - }); + // setProperty("rect", juce::var::NativeFunction { + // [=](const juce::var::NativeFunctionArgs& args) -> juce::var { + // jassert(args.numArguments == 4); + // + // const float x = args.arguments[0]; + // const float y = args.arguments[1]; + // const float width = args.arguments[2]; + // const float height = args.arguments[3]; + // + // // TODO: For some reason this operation closes the current path. + // // The API docs suggest addRectangle should be added as a new sub-path + // // leaving the previous path open. + // // Fix. + // path.addRectangle(x, y, width, height); + // + // return juce::var(); + // } + // }); + + setProperty("fillRect", juce::var::NativeFunction{ [=](const juce::var::NativeFunctionArgs& args) -> juce::var { + jassert(graphics); + jassert(args.numArguments == 4); + + const int x = args.arguments[0]; + const int y = args.arguments[1]; + const int width = args.arguments[2]; + const int height = args.arguments[3]; + + graphics->setFillType(properties.fillStyle); + graphics->fillRect(x, y, width, height); + + return juce::var(); + } }); + + setProperty("strokeRect", juce::var::NativeFunction{ [=](const juce::var::NativeFunctionArgs& args) -> juce::var { + jassert(graphics); + jassert(args.numArguments == 4); + + const int x = args.arguments[0]; + const int y = args.arguments[1]; + const int width = args.arguments[2]; + const int height = args.arguments[3]; + + graphics->setColour(properties.strokeStyle.colour); + graphics->drawRect(x, y, width, height, properties.lineWidth); + + return juce::var(); + } }); + + setProperty("strokeRoundedRect", juce::var::NativeFunction{ [=](const juce::var::NativeFunctionArgs& args) -> juce::var { + jassert(graphics); + jassert(args.numArguments == 5); + + const float x = args.arguments[0]; + const float y = args.arguments[1]; + const float width = args.arguments[2]; + const float height = args.arguments[3]; + const float cornerSize = args.arguments[4]; + + graphics->setColour(properties.strokeStyle.colour); + graphics->drawRoundedRectangle(x, y, width, height, cornerSize, (float) properties.lineWidth); + + return juce::var(); + } }); + + setProperty("fillRoundedRect", juce::var::NativeFunction{ [=](const juce::var::NativeFunctionArgs& args) -> juce::var { + jassert(graphics); + jassert(args.numArguments == 5); + + const float x = args.arguments[0]; + const float y = args.arguments[1]; + const float width = args.arguments[2]; + const float height = args.arguments[3]; + const float cornerSize = args.arguments[4]; + + graphics->setFillType(properties.fillStyle); + graphics->fillRoundedRectangle(x, y, width, height, cornerSize); + + return juce::var(); + } }); + + setProperty("clearRect", juce::var::NativeFunction{ [=](const juce::var::NativeFunctionArgs& args) -> juce::var { + jassert(graphics); + jassert(args.numArguments == 4); + + const int x = args.arguments[0]; + const int y = args.arguments[1]; + const int width = args.arguments[2]; + const int height = args.arguments[3]; + + juce::Rectangle area(x, y, width, height); + image.clear(area); + + return juce::var(); + } }); // Path functions - setProperty("beginPath", juce::var::NativeFunction { - [=](const juce::var::NativeFunctionArgs& args) -> juce::var { - jassert(graphics); - jassert(args.numArguments == 0); - juce::ignoreUnused(args); + setProperty("beginPath", juce::var::NativeFunction{ [=](const juce::var::NativeFunctionArgs& args) -> juce::var { + jassert(graphics); + jassert(args.numArguments == 0); + juce::ignoreUnused(args); - // Reset the current path on a call to beginPath on the context. - path = juce::Path(); + // Reset the current path on a call to beginPath on the context. + path = juce::Path(); - return juce::var(); - } - }); + return juce::var(); + } }); - setProperty("lineTo", juce::var::NativeFunction { - [=](const juce::var::NativeFunctionArgs& args) -> juce::var { - jassert(graphics); - jassert(args.numArguments == 2); + setProperty("lineTo", juce::var::NativeFunction{ [=](const juce::var::NativeFunctionArgs& args) -> juce::var { + jassert(graphics); + jassert(args.numArguments == 2); - const float x = args.arguments[0]; - const float y = args.arguments[1]; + const float x = args.arguments[0]; + const float y = args.arguments[1]; - path.lineTo(x, y); + path.lineTo(x, y); - return juce::var(); - } - }); + return juce::var(); + } }); - setProperty("moveTo", juce::var::NativeFunction { - [=](const juce::var::NativeFunctionArgs& args) -> juce::var { - jassert(graphics); - jassert(args.numArguments == 2); - juce::ignoreUnused(args); + setProperty("moveTo", juce::var::NativeFunction{ [=](const juce::var::NativeFunctionArgs& args) -> juce::var { + jassert(graphics); + jassert(args.numArguments == 2); + juce::ignoreUnused(args); - const float x = args.arguments[0]; - const float y = args.arguments[1]; + const float x = args.arguments[0]; + const float y = args.arguments[1]; - path.startNewSubPath(x, y); + path.startNewSubPath(x, y); - return juce::var(); - } - }); + return juce::var(); + } }); - setProperty("arc", juce::var::NativeFunction { - [=](const juce::var::NativeFunctionArgs& args) -> juce::var { - jassert(graphics); + setProperty("arc", juce::var::NativeFunction{ [=](const juce::var::NativeFunctionArgs& args) -> juce::var { + jassert(graphics); - // CanvasRenderingContext2D.arc() uses default antiClockWise false arg - jassert(args.numArguments >= 5 && args.numArguments <= 6); + // CanvasRenderingContext2D.arc() uses default antiClockWise false arg + jassert(args.numArguments >= 5 && args.numArguments <= 6); - const float x = args.arguments[0]; - const float y = args.arguments[1]; - const float radius = args.arguments[2]; - const float startAngle = args.arguments[3]; - const float endAngle = args.arguments[4]; - //TODO; Handle antiClockWise - //bool antiClockWise = args.arguments[5]; + const float x = args.arguments[0]; + const float y = args.arguments[1]; + const float radius = args.arguments[2]; + const float startAngle = args.arguments[3]; + const float endAngle = args.arguments[4]; + //TODO; Handle antiClockWise + //bool antiClockWise = args.arguments[5]; - path.addCentredArc(x, y, radius, radius, 0.0f, startAngle, endAngle, false); - return juce::var(); - } - }); + path.addCentredArc(x, y, radius, radius, 0.0f, startAngle, endAngle, false); + return juce::var(); + } }); - setProperty("quadraticCurveTo", juce::var::NativeFunction { - [=](const juce::var::NativeFunctionArgs& args) -> juce::var { - jassert(graphics); - jassert(args.numArguments == 4); + setProperty("quadraticCurveTo", juce::var::NativeFunction{ [=](const juce::var::NativeFunctionArgs& args) -> juce::var { + jassert(graphics); + jassert(args.numArguments == 4); - const float controlPointX = args.arguments[0]; - const float controlPointY = args.arguments[1]; - const float endPointX = args.arguments[2]; - const float endPointY = args.arguments[3]; + const float controlPointX = args.arguments[0]; + const float controlPointY = args.arguments[1]; + const float endPointX = args.arguments[2]; + const float endPointY = args.arguments[3]; - path.quadraticTo(controlPointX, controlPointY, endPointX, endPointY); + path.quadraticTo(controlPointX, controlPointY, endPointX, endPointY); - return juce::var(); - } - }); + return juce::var(); + } }); //TODO: Implement CanvasRenderingContext2D.bezierCurveTo(). Will use juce::Path::cubicTo - setProperty("closePath", juce::var::NativeFunction { - [=](const juce::var::NativeFunctionArgs& args) -> juce::var { - jassert(graphics); - jassert(args.numArguments == 0); - juce::ignoreUnused(args); + setProperty("closePath", juce::var::NativeFunction{ [=](const juce::var::NativeFunctionArgs& args) -> juce::var { + jassert(graphics); + jassert(args.numArguments == 0); + juce::ignoreUnused(args); - path.closeSubPath(); + path.closeSubPath(); - return juce::var(); - } - }); + return juce::var(); + } }); - setProperty("stroke", juce::var::NativeFunction { - [=](const juce::var::NativeFunctionArgs& args) -> juce::var { - jassert(graphics); - jassert(args.numArguments == 0); - juce::ignoreUnused(args); + setProperty("stroke", juce::var::NativeFunction{ [=](const juce::var::NativeFunctionArgs& args) -> juce::var { + jassert(graphics); + jassert(args.numArguments == 0); + juce::ignoreUnused(args); - graphics->setColour(properties.strokeStyle.colour); - graphics->strokePath(path, juce::PathStrokeType((float)properties.lineWidth)); + graphics->setColour(properties.strokeStyle.colour); + graphics->strokePath(path, juce::PathStrokeType((float) properties.lineWidth)); - return juce::var(); - } - }); + return juce::var(); + } }); - setProperty("fill", juce::var::NativeFunction { - [=](const juce::var::NativeFunctionArgs& args) -> juce::var { - jassert(graphics); - jassert(args.numArguments == 0); - juce::ignoreUnused(args); + setProperty("fill", juce::var::NativeFunction{ [=](const juce::var::NativeFunctionArgs& args) -> juce::var { + jassert(graphics); + jassert(args.numArguments == 0); + juce::ignoreUnused(args); - graphics->setColour(properties.fillStyle.colour); - graphics->fillPath(path); + graphics->setColour(properties.fillStyle.colour); + graphics->fillPath(path); - return juce::var(); - } - }); + return juce::var(); + } }); // Transforms - setProperty("rotate", juce::var::NativeFunction { - [=](const juce::var::NativeFunctionArgs& args) -> juce::var { - jassert(graphics); - jassert(args.numArguments == 1); - - const float angle = args.arguments[0]; - - auto transform = juce::AffineTransform::rotation(angle); - graphics->addTransform(transform); - transformStack.push_back(transform.inverted()); - - return juce::var(); - } - }); - - setProperty("translate", juce::var::NativeFunction { - [=](const juce::var::NativeFunctionArgs& args) -> juce::var { - jassert(graphics); - jassert(args.numArguments == 2); - - const float x = args.arguments[0]; - const float y = args.arguments[1]; - - auto transform = juce::AffineTransform::translation(x, y); - graphics->addTransform(transform); - transformStack.push_back(transform.inverted()); - - return juce::var(); - } - }); - - setProperty("setTransform", juce::var::NativeFunction { - [=](const juce::var::NativeFunctionArgs& args) -> juce::var { - jassert(graphics); - jassert(args.numArguments == 6); - - const float mat00 = args.arguments[0]; - const float mat01 = args.arguments[1]; - const float mat02 = args.arguments[2]; - const float mat10 = args.arguments[3]; - const float mat11 = args.arguments[4]; - const float mat12 = args.arguments[5]; - - auto transform = juce::AffineTransform(mat00, mat01, mat02, mat10, mat11, mat12); - graphics->addTransform(transform); - transformStack.push_back(transform.inverted()); - - return juce::var(); - } - }); - - setProperty("resetTransform", juce::var::NativeFunction { - [=](const juce::var::NativeFunctionArgs& args) -> juce::var { - jassert(graphics); - jassert(args.numArguments == 0); - juce::ignoreUnused(args); - - while (!transformStack.empty()) - { - graphics->addTransform(transformStack.back()); - transformStack.pop_back(); - } - - transformStack.clear(); - - return juce::var(); - } - }); + setProperty("rotate", juce::var::NativeFunction{ [=](const juce::var::NativeFunctionArgs& args) -> juce::var { + jassert(graphics); + jassert(args.numArguments == 1); - // drawImage support - setProperty("drawImage", juce::var::NativeFunction { - [=](const juce::var::NativeFunctionArgs& args) -> juce::var { - jassert(graphics); - jassert(args.numArguments >= 3 && args.numArguments <= 5); + const float angle = args.arguments[0]; + + auto transform = juce::AffineTransform::rotation(angle); + graphics->addTransform(transform); + transformStack.push_back(transform.inverted()); + + return juce::var(); + } }); + + setProperty("translate", juce::var::NativeFunction{ [=](const juce::var::NativeFunctionArgs& args) -> juce::var { + jassert(graphics); + jassert(args.numArguments == 2); + + const float x = args.arguments[0]; + const float y = args.arguments[1]; + + auto transform = juce::AffineTransform::translation(x, y); + graphics->addTransform(transform); + transformStack.push_back(transform.inverted()); + + return juce::var(); + } }); + + setProperty("setTransform", juce::var::NativeFunction{ [=](const juce::var::NativeFunctionArgs& args) -> juce::var { + jassert(graphics); + jassert(args.numArguments == 6); + + const float mat00 = args.arguments[0]; + const float mat01 = args.arguments[1]; + const float mat02 = args.arguments[2]; + const float mat10 = args.arguments[3]; + const float mat11 = args.arguments[4]; + const float mat12 = args.arguments[5]; + + auto transform = juce::AffineTransform(mat00, mat01, mat02, mat10, mat11, mat12); + graphics->addTransform(transform); + transformStack.push_back(transform.inverted()); - const juce::String svg = args.arguments[0].toString(); - const float xPos = args.arguments[1]; - const float yPos = args.arguments[2]; + return juce::var(); + } }); - //TODO: Add support for drawimage source width and source height to draw sub rect of an image. - // ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight); + setProperty("resetTransform", juce::var::NativeFunction{ [=](const juce::var::NativeFunctionArgs& args) -> juce::var { + jassert(graphics); + jassert(args.numArguments == 0); + juce::ignoreUnused(args); - std::unique_ptr svgElement(juce::XmlDocument::parse(svg)); + while (! transformStack.empty()) + { + graphics->addTransform(transformStack.back()); + transformStack.pop_back(); + } + + transformStack.clear(); - if (!svgElement) - { - DBG("\"WARNING: Invalid SVG string supplied to `drawImage`.\""); return juce::var(); - } + } }); + + // drawImage support + setProperty("drawImage", juce::var::NativeFunction{ [=](const juce::var::NativeFunctionArgs& args) -> juce::var { + jassert(graphics); + jassert(args.numArguments >= 3 && args.numArguments <= 5); - std::unique_ptr svgDrawable(juce::Drawable::createFromSVG(*svgElement)); + const juce::String svg = args.arguments[0].toString(); + const float xPos = args.arguments[1]; + const float yPos = args.arguments[2]; - if (args.numArguments == 5) - { - const float destWidth = args.arguments[3]; - const float destHeight = args.arguments[4]; - const auto bounds = juce::Rectangle(xPos, yPos, destWidth, destHeight); + //TODO: Add support for drawimage source width and source height to draw sub rect of an image. + // ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight); - svgDrawable->setTransformToFit(bounds, juce::RectanglePlacement::stretchToFit); - svgDrawable->draw(*graphics, 1.0f); - } - else - { - svgDrawable->drawAt(*graphics, xPos, yPos, 1.0); - } + std::unique_ptr svgElement(juce::XmlDocument::parse(svg)); - return juce::var(); - } - }); + if (! svgElement) + { + DBG("\"WARNING: Invalid SVG string supplied to `drawImage`.\""); + return juce::var(); + } + + std::unique_ptr svgDrawable(juce::Drawable::createFromSVG(*svgElement)); + + if (args.numArguments == 5) + { + const float destWidth = args.arguments[3]; + const float destHeight = args.arguments[4]; + const auto bounds = juce::Rectangle(xPos, yPos, destWidth, destHeight); + + svgDrawable->setTransformToFit(bounds, juce::RectanglePlacement::stretchToFit); + svgDrawable->draw(*graphics, 1.0f); + } + else + { + svgDrawable->drawAt(*graphics, xPos, yPos, 1.0); + } + + return juce::var(); + } }); // Text functions - setProperty("strokeText", juce::var::NativeFunction { - [=](const juce::var::NativeFunctionArgs& args) -> juce::var { - jassert(graphics); - jassert(args.numArguments >= 3 && args.numArguments <= 4); + setProperty("strokeText", juce::var::NativeFunction{ [=](const juce::var::NativeFunctionArgs& args) -> juce::var { + jassert(graphics); + jassert(args.numArguments >= 3 && args.numArguments <= 4); - const juce::String text = args.arguments[0].toString(); - const float xPos = args.arguments[1]; - const float yPos = args.arguments[2]; + const juce::String text = args.arguments[0].toString(); + const float xPos = args.arguments[1]; + const float yPos = args.arguments[2]; - // Default maxLineWidth to full context width - float maxLineWidth = (float)ctxWidth; + // Default maxLineWidth to full context width + float maxLineWidth = (float) ctxWidth; - if (args.numArguments == 4) - maxLineWidth = args.arguments[3]; + if (args.numArguments == 4) + maxLineWidth = args.arguments[3]; - juce::Path textPath; - juce::GlyphArrangement glyphArrangement; + juce::Path textPath; + juce::GlyphArrangement glyphArrangement; - glyphArrangement.addJustifiedText(properties.font, text, xPos, yPos, maxLineWidth, properties.textAlign); - glyphArrangement.createPath(textPath); + glyphArrangement.addJustifiedText(properties.font, text, xPos, yPos, maxLineWidth, properties.textAlign); + glyphArrangement.createPath(textPath); - graphics->setColour(properties.strokeStyle.colour); - graphics->strokePath(textPath, juce::PathStrokeType((float)properties.lineWidth)); + graphics->setColour(properties.strokeStyle.colour); + graphics->strokePath(textPath, juce::PathStrokeType((float) properties.lineWidth)); - return juce::var(); - } - }); + return juce::var(); + } }); - setProperty("fillText", juce::var::NativeFunction { - [=](const juce::var::NativeFunctionArgs& args) -> juce::var { - jassert(graphics); - jassert(args.numArguments >= 3 && args.numArguments <= 4); + setProperty("fillText", juce::var::NativeFunction{ [=](const juce::var::NativeFunctionArgs& args) -> juce::var { + jassert(graphics); + jassert(args.numArguments >= 3 && args.numArguments <= 4); - const juce::String text = args.arguments[0].toString(); - const float xPos = args.arguments[1]; - const float yPos = args.arguments[2]; + const juce::String text = args.arguments[0].toString(); + const float xPos = args.arguments[1]; + const float yPos = args.arguments[2]; - // Default maxLineWidth to full context width - float maxLineWidth = (float)ctxWidth; + // Default maxLineWidth to full context width + float maxLineWidth = (float) ctxWidth; - if (args.numArguments == 4) - maxLineWidth = args.arguments[3]; + if (args.numArguments == 4) + maxLineWidth = args.arguments[3]; - juce::Path textPath; - juce::GlyphArrangement glyphArrangement; + juce::Path textPath; + juce::GlyphArrangement glyphArrangement; - glyphArrangement.addJustifiedText(properties.font, text, xPos, yPos, maxLineWidth, properties.textAlign); - glyphArrangement.createPath(textPath); + glyphArrangement.addJustifiedText(properties.font, text, xPos, yPos, maxLineWidth, properties.textAlign); + glyphArrangement.createPath(textPath); - graphics->setFillType(properties.fillStyle); - graphics->fillPath(textPath); + graphics->setFillType(properties.fillStyle); + graphics->fillPath(textPath); - return juce::var(); - } - }); + return juce::var(); + } }); } //============================================================================== - int ctxWidth; - int ctxHeight; + int ctxWidth; + int ctxHeight; - juce::Image image; - std::unique_ptr graphics; - juce::Path path; - Properties properties; + juce::Image image; + std::unique_ptr graphics; + juce::Path path; + Properties properties; std::vector transformStack; }; @@ -669,7 +617,7 @@ namespace blueprint public: //============================================================================== static const inline juce::Identifier animateProp = "animate"; - static const inline juce::Identifier onDrawProp = "onDraw"; + static const inline juce::Identifier onDrawProp = "onDraw"; //============================================================================== CanvasView() @@ -684,7 +632,7 @@ namespace blueprint } //============================================================================== - void setProperty (const juce::Identifier& name, const juce::var& value) override + void setProperty(const juce::Identifier& name, const juce::var& value) override { View::setProperty(name, value); @@ -692,10 +640,10 @@ namespace blueprint { bool shouldAnimate = value; - if (shouldAnimate && !isTimerRunning()) + if (shouldAnimate && ! isTimerRunning()) startTimerHz(45); - if (!shouldAnimate && isTimerRunning()) + if (! shouldAnimate && isTimerRunning()) stopTimer(); } } @@ -707,7 +655,7 @@ namespace blueprint } //============================================================================== - void paint (juce::Graphics& g) override + void paint(juce::Graphics& g) override { View::paint(g); @@ -716,8 +664,8 @@ namespace blueprint if (props.contains(onDrawProp) && props[onDrawProp].isMethod()) { - std::vector jsArgs {{ctx.get()}}; - juce::var::NativeFunctionArgs nfArgs (juce::var(), jsArgs.data(), static_cast(jsArgs.size())); + std::vector jsArgs{ { ctx.get() } }; + juce::var::NativeFunctionArgs nfArgs(juce::var(), jsArgs.data(), static_cast(jsArgs.size())); std::invoke(props[onDrawProp].getNativeFunction(), nfArgs); } @@ -740,7 +688,7 @@ namespace blueprint juce::ReferenceCountedObjectPtr ctx; //============================================================================== - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CanvasView) + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CanvasView) }; -} +} // namespace blueprint diff --git a/blueprint/core/blueprint_EcmascriptEngine.cpp b/blueprint/core/blueprint_EcmascriptEngine.cpp index f0dfc8ee..ab5e353f 100644 --- a/blueprint/core/blueprint_EcmascriptEngine.cpp +++ b/blueprint/core/blueprint_EcmascriptEngine.cpp @@ -18,7 +18,7 @@ * the 8.1 SDK, but the GetSystemTimePreciseAsFileTime() call used in here is * just not supported without the 8.1 dll available. */ -#if defined (_WIN32) || defined (_WIN64) +#if defined(_WIN32) || defined(_WIN64) #define DUK_USE_DATE_NOW_WINDOWS 1 #endif @@ -27,30 +27,30 @@ * duktape and juce including parts of the winsock2 API. There may be a better way to * resolve this. */ -#if defined (_WIN32) || defined (_WIN64) +#if defined(_WIN32) || defined(_WIN64) #define _WINSOCKAPI_ #endif #if _MSC_VER - #pragma warning(push) +#pragma warning(push) #elif __clang__ - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wextra-semi" - #pragma clang diagnostic ignored "-Wsign-conversion" - #pragma clang diagnostic ignored "-Wswitch-enum" - #pragma clang diagnostic ignored "-Wunused-parameter" - #if __clang_major__ > 10 - #pragma clang diagnostic ignored "-Wc++98-compat-extra-semi" - #pragma clang diagnostic ignored "-Wimplicit-int-conversion" - #else - #pragma clang diagnostic ignored "-Wconversion" - #endif +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wextra-semi" +#pragma clang diagnostic ignored "-Wsign-conversion" +#pragma clang diagnostic ignored "-Wswitch-enum" +#pragma clang diagnostic ignored "-Wunused-parameter" +#if __clang_major__ > 10 +#pragma clang diagnostic ignored "-Wc++98-compat-extra-semi" +#pragma clang diagnostic ignored "-Wimplicit-int-conversion" +#else +#pragma clang diagnostic ignored "-Wconversion" +#endif #elif __GNUC__ - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" - #pragma GCC diagnostic ignored "-Wsign-conversion" - #pragma GCC diagnostic ignored "-Wswitch-enum" - #pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" +#pragma GCC diagnostic ignored "-Wsign-conversion" +#pragma GCC diagnostic ignored "-Wswitch-enum" +#pragma GCC diagnostic ignored "-Wunused-parameter" #endif // We rely on the JUCE_DEBUG macro in duk_config.h at the moment to determine @@ -59,36 +59,33 @@ // configs. #include -#include #include +#include -#if defined (_WIN32) || defined (_WIN64) - #include +#if defined(_WIN32) || defined(_WIN64) +#include #else - #include +#include #endif -#include -#include #include +#include +#include #if _MSC_VER #elif __clang__ - #pragma clang diagnostic pop +#pragma clang diagnostic pop #elif __GNUC__ - #pragma GCC diagnostic pop +#pragma GCC diagnostic pop #endif #include "blueprint_EcmascriptEngine.h" - namespace blueprint { - namespace detail { - - static void fatalErrorHandler (void* udata, const char* msg) + static void fatalErrorHandler(void* udata, const char* msg) { (void) udata; // Ignored in this case, silence warning throw EcmascriptEngine::FatalError(msg); @@ -141,7 +138,7 @@ namespace blueprint } } - } + } // namespace detail //============================================================================== struct EcmascriptEngine::Pimpl : private juce::Timer @@ -155,14 +152,17 @@ namespace blueprint } //============================================================================== - juce::var evaluateInline (const juce::String& code) + juce::var evaluateInline(const juce::String& code) { jassert(code.isNotEmpty()); auto* ctxRawPtr = dukContext.get(); - try { + try + { detail::safeEvalString(ctxRawPtr, code); - } catch (Error const& err) { + } + catch (Error const& err) + { reset(); throw err; } @@ -173,16 +173,19 @@ namespace blueprint return result; } - juce::var evaluate (const juce::File& code) + juce::var evaluate(const juce::File& code) { jassert(code.existsAsFile()); jassert(code.loadFileAsString().isNotEmpty()); auto* ctxRawPtr = dukContext.get(); - try { + try + { detail::safeCompileFile(ctxRawPtr, code); detail::safeCall(ctxRawPtr, 0); - } catch (Error const& err) { + } + catch (Error const& err) + { reset(); throw err; } @@ -195,7 +198,7 @@ namespace blueprint } //============================================================================== - void registerNativeProperty (const juce::String& name, const juce::var& value) + void registerNativeProperty(const juce::String& name, const juce::var& value) { auto* ctxRawPtr = dukContext.get(); @@ -205,13 +208,16 @@ namespace blueprint duk_pop(ctxRawPtr); } - void registerNativeProperty (const juce::String& target, const juce::String& name, const juce::var& value) + void registerNativeProperty(const juce::String& target, const juce::String& name, const juce::var& value) { auto* ctxRawPtr = dukContext.get(); - try { + try + { detail::safeEvalString(ctxRawPtr, target); - } catch (Error const& err) { + } + catch (Error const& err) + { reset(); throw err; } @@ -223,14 +229,16 @@ namespace blueprint } //============================================================================== - juce::var invoke (const juce::String& name, const std::vector& vargs) + juce::var invoke(const juce::String& name, const std::vector& vargs) { auto* ctxRawPtr = dukContext.get(); - try { + try + { detail::safeEvalString(ctxRawPtr, name); - if (!duk_is_function(ctxRawPtr, -1)) { + if (! duk_is_function(ctxRawPtr, -1)) + { throw Error("Invocation failed, target is not a function."); } @@ -243,7 +251,9 @@ namespace blueprint // Invocation detail::safeCall(ctxRawPtr, nargs); - } catch (Error const& err) { + } + catch (Error const& err) + { reset(); throw err; } @@ -257,8 +267,9 @@ namespace blueprint struct TimeoutFunctionManager : private juce::MultiTimer { - ~TimeoutFunctionManager() override { - for(const auto &[id, timer] : timeoutFunctions) + ~TimeoutFunctionManager() override + { + for (const auto& [id, timer] : timeoutFunctions) stopTimer(id); } @@ -266,12 +277,12 @@ namespace blueprint { stopTimer(id); const auto f = timeoutFunctions.find(id); - if(f != timeoutFunctions.cend()) + if (f != timeoutFunctions.cend()) timeoutFunctions.erase(f); return juce::var(); } - int newTimeout(const juce::var::NativeFunction f, const int timeoutMillis, const std::vector&& args, const bool repeats=false) + int newTimeout(const juce::var::NativeFunction f, const int timeoutMillis, const std::vector&& args, const bool repeats = false) { static int nextId = 0; timeoutFunctions.emplace(nextId, TimeoutFunction(f, std::move(args), repeats)); @@ -282,11 +293,11 @@ namespace blueprint void timerCallback(int id) override { const auto f = timeoutFunctions.find(id); - if(f != timeoutFunctions.cend()) + if (f != timeoutFunctions.cend()) { const auto cb = f->second; std::invoke(cb.f, juce::var::NativeFunctionArgs(juce::var(), cb.args.data(), static_cast(cb.args.size()))); - if(!cb.repeats) + if (! cb.repeats) { stopTimer(id); timeoutFunctions.erase(f); @@ -294,18 +305,18 @@ namespace blueprint } } - private: - struct TimeoutFunction - { - TimeoutFunction(const juce::var::NativeFunction _f, const std::vector &&_args, const bool _repeats=false) + private: + struct TimeoutFunction + { + TimeoutFunction(const juce::var::NativeFunction _f, const std::vector&& _args, const bool _repeats = false) : f(_f), args(std::move(_args)), repeats(_repeats) {} - const juce::var::NativeFunction f; - std::vector args; - const bool repeats; - }; + const juce::var::NativeFunction f; + std::vector args; + const bool repeats; + }; - std::map timeoutFunctions; + std::map timeoutFunctions; }; // IsSetter is true for setTimeout / setInterval @@ -313,32 +324,30 @@ namespace blueprint template void registerNativeTimerFunction(const char* name, MethodType method) { - registerNativeProperty(name, juce::var::NativeFunction([this, name, method] (const juce::var::NativeFunctionArgs& _args) -> juce::var { - if constexpr (IsSetter) - { - if(_args.numArguments < 2 || !_args.arguments[0].isMethod() || !_args.arguments[1].isDouble()) - throw Error(juce::String(name) + " requires a callback and time in milliseconds"); - // build a vector holding all additional arguments - std::vector args(_args.arguments + 2, _args.arguments + _args.numArguments); - return (this->timeoutsManager.get()->*method)(_args.arguments[0].getNativeFunction(), _args.arguments[1], std::move(args), Repeats); - } - else - { - if(_args.numArguments < 1 || !_args.arguments[0].isDouble()) - throw Error(juce::String(name) + " requires an integer ID of the timer to clear"); - return (this->timeoutsManager.get()->*method)(_args.arguments[0]); - } - })); + registerNativeProperty(name, juce::var::NativeFunction([this, name, method](const juce::var::NativeFunctionArgs& _args) -> juce::var { + if constexpr (IsSetter) + { + if (_args.numArguments < 2 || ! _args.arguments[0].isMethod() || ! _args.arguments[1].isDouble()) + throw Error(juce::String(name) + " requires a callback and time in milliseconds"); + // build a vector holding all additional arguments + std::vector args(_args.arguments + 2, _args.arguments + _args.numArguments); + return (this->timeoutsManager.get()->*method)(_args.arguments[0].getNativeFunction(), _args.arguments[1], std::move(args), Repeats); + } + else + { + if (_args.numArguments < 1 || ! _args.arguments[0].isDouble()) + throw Error(juce::String(name) + " requires an integer ID of the timer to clear"); + return (this->timeoutsManager.get()->*method)(_args.arguments[0]); + } + })); } void registerTimerGlobals() { registerNativeTimerFunction( - "setTimeout", &TimeoutFunctionManager::newTimeout - ); + "setTimeout", &TimeoutFunctionManager::newTimeout); registerNativeTimerFunction( - "setInterval", &TimeoutFunctionManager::newTimeout - ); + "setInterval", &TimeoutFunctionManager::newTimeout); registerNativeTimerFunction("clearTimeout", &TimeoutFunctionManager::clearTimeout); registerNativeTimerFunction("clearInterval", &TimeoutFunctionManager::clearTimeout); } @@ -350,9 +359,8 @@ namespace blueprint // Allocate a new js heap dukContext = std::shared_ptr( - duk_create_heap (nullptr, nullptr, nullptr, nullptr, detail::fatalErrorHandler), - duk_destroy_heap - ); + duk_create_heap(nullptr, nullptr, nullptr, nullptr, detail::fatalErrorHandler), + duk_destroy_heap); // Add console.log support auto* ctxRawPtr = dukContext.get(); @@ -360,7 +368,7 @@ namespace blueprint // Install a pointer back to this EcmascriptEngine instance duk_push_global_stash(ctxRawPtr); - duk_push_pointer(ctxRawPtr, (void *) this); + duk_push_pointer(ctxRawPtr, (void*) this); duk_put_prop_string(ctxRawPtr, -2, DUK_HIDDEN_SYMBOL("__EcmascriptEngineInstance__")); duk_pop(ctxRawPtr); @@ -379,15 +387,15 @@ namespace blueprint duk_trans_socket_init(); duk_trans_socket_waitconn(); - duk_debugger_attach(ctxRawPtr, + duk_debugger_attach( + ctxRawPtr, duk_trans_socket_read_cb, duk_trans_socket_write_cb, duk_trans_socket_peek_cb, duk_trans_socket_read_flush_cb, duk_trans_socket_write_flush_cb, nullptr, - [](duk_context*, void* data) - { + [](duk_context*, void* data) { duk_trans_socket_finish(); auto engine = static_cast(data); @@ -402,18 +410,19 @@ namespace blueprint void debuggerDetach() { if (auto* dc = dukContext.get()) - duk_debugger_detach (dc); + duk_debugger_detach(dc); } //============================================================================== void timerCallback() override { if (auto* dc = dukContext.get()) - duk_debugger_cooperate (dc); + duk_debugger_cooperate(dc); } //============================================================================== - struct LambdaHelper { + struct LambdaHelper + { LambdaHelper(juce::var::NativeFunction fn, uint32_t _id) : callback(std::move(fn)), id(_id) {} @@ -446,11 +455,7 @@ namespace blueprint // Now we can invoke the user method with its arguments try { - result = std::invoke(helper->callback, juce::var::NativeFunctionArgs( - juce::var(), - args.data(), - static_cast(args.size()) - )); + result = std::invoke(helper->callback, juce::var::NativeFunctionArgs(juce::var(), args.data(), static_cast(args.size()))); } catch (Error& err) { @@ -479,23 +484,19 @@ namespace blueprint // Retrieve the lambda helper duk_push_current_function(ctx); const auto magic = duk_get_magic(ctx, -1); - auto& helper = engine->temporaryReleasePool[static_cast (magic + 128)]; + auto& helper = engine->temporaryReleasePool[static_cast(magic + 128)]; duk_pop(ctx); // Now we can collect our args const auto nargs = duk_get_top(ctx); std::vector args; - args.reserve(static_cast (nargs)); + args.reserve(static_cast(nargs)); for (int i = 0; i < nargs; ++i) args.push_back(engine->readVarFromDukStack(engine->dukContext, i)); // Now we can invoke the user method with its arguments - const auto result = std::invoke(helper->callback, juce::var::NativeFunctionArgs( - juce::var(), - args.data(), - static_cast(args.size()) - )); + const auto result = std::invoke(helper->callback, juce::var::NativeFunctionArgs(juce::var(), args.data(), static_cast(args.size()))); // For an undefined result, return 0 to notify the duktape interpreter if (result.isUndefined()) @@ -506,7 +507,7 @@ namespace blueprint return 1; } - static duk_ret_t callbackFinalizer (duk_context* ctx) + static duk_ret_t callbackFinalizer(duk_context* ctx) { // First we have to retrieve the actual function pointer and our engine pointer // See: https://duktape.org/guide.html#hidden-symbol-properties @@ -536,13 +537,13 @@ namespace blueprint //============================================================================== /** Helper for cleaning up native function temporaries. */ - void removeLambdaHelper (LambdaHelper* helper) + void removeLambdaHelper(LambdaHelper* helper) { persistentReleasePool.erase(helper->id); } /** Helper for pushing a juce::var to the duktape stack. */ - void pushVarToDukStack (std::shared_ptr ctx, const juce::var& v, bool persistNativeFunctions = false) + void pushVarToDukStack(std::shared_ptr ctx, const juce::var& v, bool persistNativeFunctions = false) { auto* ctxRawPtr = dukContext.get(); @@ -594,16 +595,16 @@ namespace blueprint // Now we assign the pointers as properties of the wrapper function auto helper = std::make_unique(v.getNativeFunction(), nextHelperId++); - duk_push_pointer(ctxRawPtr, (void *) helper.get()); + duk_push_pointer(ctxRawPtr, (void*) helper.get()); duk_put_prop_string(ctxRawPtr, -2, DUK_HIDDEN_SYMBOL("LambdaHelperPtr")); - duk_push_pointer(ctxRawPtr, (void *) this); + duk_push_pointer(ctxRawPtr, (void*) this); duk_put_prop_string(ctxRawPtr, -2, DUK_HIDDEN_SYMBOL("EnginePtr")); // Now we prepare the finalizer duk_push_c_function(ctxRawPtr, LambdaHelper::callbackFinalizer, 1); - duk_push_pointer(ctxRawPtr, (void *) helper.get()); + duk_push_pointer(ctxRawPtr, (void*) helper.get()); duk_put_prop_string(ctxRawPtr, -2, DUK_HIDDEN_SYMBOL("LambdaHelperPtr")); - duk_push_pointer(ctxRawPtr, (void *) this); + duk_push_pointer(ctxRawPtr, (void*) this); duk_put_prop_string(ctxRawPtr, -2, DUK_HIDDEN_SYMBOL("EnginePtr")); duk_set_finalizer(ctxRawPtr, -2); @@ -623,7 +624,7 @@ namespace blueprint auto magic = nextMagicInt++; duk_push_c_lightfunc(ctxRawPtr, LambdaHelper::invokeFromDukContextLightFunc, DUK_VARARGS, 15, magic); - temporaryReleasePool[static_cast (magic + 128)] = std::move(helper); + temporaryReleasePool[static_cast(magic + 128)] = std::move(helper); if (nextMagicInt >= 127) nextMagicInt = -128; @@ -637,7 +638,7 @@ namespace blueprint } /** Helper for reading from the duktape stack to a juce::var instance. */ - juce::var readVarFromDukStack (std::shared_ptr ctx, duk_idx_t idx) + juce::var readVarFromDukStack(std::shared_ptr ctx, duk_idx_t idx) { auto* ctxRawPtr = dukContext.get(); juce::var value; @@ -681,13 +682,15 @@ namespace blueprint if (duk_is_function(ctxRawPtr, idx) || duk_is_lightfunc(ctxRawPtr, idx)) { - struct CallbackHelper { + struct CallbackHelper + { CallbackHelper(std::weak_ptr _weakContext) - : weakContext(_weakContext) - , funcId(juce::String("__blueprintCallback__") + juce::Uuid().toString()) {} + : weakContext(_weakContext), funcId(juce::String("__blueprintCallback__") + juce::Uuid().toString()) {} - ~CallbackHelper() { - if (auto spt = weakContext.lock()) { + ~CallbackHelper() + { + if (auto spt = weakContext.lock()) + { duk_push_global_stash(spt.get()); duk_del_prop_string(spt.get(), -1, funcId.toRawUTF8()); duk_pop(spt.get()); @@ -709,12 +712,12 @@ namespace blueprint // Next we create a var::NativeFunction that captures the function // id and knows how to invoke it - value = juce::var::NativeFunction { + value = juce::var::NativeFunction{ [this, weakContext = std::weak_ptr(ctx), helper](const juce::var::NativeFunctionArgs& args) -> juce::var { auto sharedContext = weakContext.lock(); // If our context disappeared, we return early - if (!sharedContext) + if (! sharedContext) return juce::var(); auto* rawPtr = sharedContext.get(); @@ -724,7 +727,7 @@ namespace blueprint duk_push_global_stash(rawPtr); duk_get_prop_string(rawPtr, -1, helper->funcId.toRawUTF8()); - if (!(duk_is_lightfunc(rawPtr, -1) || duk_is_function(rawPtr, -1))) + if (! (duk_is_lightfunc(rawPtr, -1) || duk_is_function(rawPtr, -1))) throw Error("Global callback not found.", "", detail::getContextDump(rawPtr)); // Push the args to the duktape stack @@ -734,9 +737,12 @@ namespace blueprint pushVarToDukStack(sharedContext, args.arguments[i]); // Invocation - try { + try + { detail::safeCall(rawPtr, args.numArguments); - } catch (Error const& err) { + } + catch (Error const& err) + { reset(); throw err; } @@ -813,7 +819,7 @@ namespace blueprint Without the initialiser, the console app would always crash on exit, and things will probably not get cleaned up. */ - jassert (juce::MessageManager::getInstanceWithoutCreating() != nullptr); + jassert(juce::MessageManager::getInstanceWithoutCreating() != nullptr); } EcmascriptEngine::~EcmascriptEngine() @@ -821,40 +827,40 @@ namespace blueprint } //============================================================================== - juce::var EcmascriptEngine::evaluateInline (const juce::String& code) + juce::var EcmascriptEngine::evaluateInline(const juce::String& code) { return mPimpl->evaluateInline(code); } - juce::var EcmascriptEngine::evaluate (const juce::File& code) + juce::var EcmascriptEngine::evaluate(const juce::File& code) { return mPimpl->evaluate(code); } //============================================================================== - void EcmascriptEngine::registerNativeMethod (const juce::String& name, juce::var::NativeFunction fn) + void EcmascriptEngine::registerNativeMethod(const juce::String& name, juce::var::NativeFunction fn) { registerNativeProperty(name, juce::var(fn)); } - void EcmascriptEngine::registerNativeMethod (const juce::String& target, const juce::String& name, juce::var::NativeFunction fn) + void EcmascriptEngine::registerNativeMethod(const juce::String& target, const juce::String& name, juce::var::NativeFunction fn) { registerNativeProperty(target, name, juce::var(fn)); } //============================================================================== - void EcmascriptEngine::registerNativeProperty (const juce::String& name, const juce::var& value) + void EcmascriptEngine::registerNativeProperty(const juce::String& name, const juce::var& value) { mPimpl->registerNativeProperty(name, value); } - void EcmascriptEngine::registerNativeProperty (const juce::String& target, const juce::String& name, const juce::var& value) + void EcmascriptEngine::registerNativeProperty(const juce::String& target, const juce::String& name, const juce::var& value) { mPimpl->registerNativeProperty(target, name, value); } //============================================================================== - juce::var EcmascriptEngine::invoke (const juce::String& name, const std::vector& vargs) + juce::var EcmascriptEngine::invoke(const juce::String& name, const std::vector& vargs) { return mPimpl->invoke(name, vargs); } @@ -875,4 +881,4 @@ namespace blueprint mPimpl->debuggerDetach(); } -} +} // namespace blueprint diff --git a/blueprint/core/blueprint_EcmascriptEngine.h b/blueprint/core/blueprint_EcmascriptEngine.h index 12c4f505..e7c4b39a 100644 --- a/blueprint/core/blueprint_EcmascriptEngine.h +++ b/blueprint/core/blueprint_EcmascriptEngine.h @@ -11,10 +11,8 @@ #include - namespace blueprint { - //============================================================================== /** The EcmascriptEngine provides a flexible ECMAScript 5 compliant JavaScript engine * with an interface implemented by Duktape, but which may be implemented by one of @@ -33,7 +31,8 @@ namespace blueprint * * We provide the JavaScript stack trace in the `stack` member. */ - struct Error : public std::runtime_error { + struct Error : public std::runtime_error + { Error(const juce::String& msg) : std::runtime_error(msg.toStdString()) {} @@ -53,7 +52,8 @@ namespace blueprint * In the event this error is thrown, the engine is to be considered * unrecoverable, and it is up to the user to address how to proceed. */ - struct FatalError : public std::runtime_error { + struct FatalError : public std::runtime_error + { FatalError(const juce::String& msg) : std::runtime_error(msg.toStdString()) {} }; @@ -64,12 +64,12 @@ namespace blueprint * @returns juce::var result of the evaluation * @throws EcmascriptEngine::Error in the event of an evaluation error */ - juce::var evaluateInline (const juce::String& code); - juce::var evaluate (const juce::File& code); + juce::var evaluateInline(const juce::String& code); + juce::var evaluate(const juce::File& code); //============================================================================== /** Registers a native method by the given name in the global namespace. */ - void registerNativeMethod (const juce::String&, juce::var::NativeFunction fn); + void registerNativeMethod(const juce::String&, juce::var::NativeFunction fn); /** Registers a native method by the given name on the target object. * @@ -88,11 +88,11 @@ namespace blueprint * * @throws EcmascriptEngine::Error in the event of an evaluation error */ - void registerNativeMethod (const juce::String&, const juce::String&, juce::var::NativeFunction fn); + void registerNativeMethod(const juce::String&, const juce::String&, juce::var::NativeFunction fn); //============================================================================== /** Registers a native value by the given name in the global namespace. */ - void registerNativeProperty (const juce::String&, const juce::var&); + void registerNativeProperty(const juce::String&, const juce::var&); /** Registers a native value by the given name on the target object. * @@ -108,7 +108,7 @@ namespace blueprint * * @throws EcmascriptEngine::Error in the event of an evaluation error */ - void registerNativeProperty (const juce::String&, const juce::String&, const juce::var&); + void registerNativeProperty(const juce::String&, const juce::String&, const juce::var&); //============================================================================== /** Invokes a method, applying the given args, inside the interpreter. @@ -122,7 +122,7 @@ namespace blueprint * @returns juce::var result of the invocation * @throws EcmascriptEngine::Error in the event of an error */ - juce::var invoke (const juce::String& name, const std::vector& vargs); + juce::var invoke(const juce::String& name, const std::vector& vargs); /** Invokes a method with the given args inside the interpreter. * @@ -136,7 +136,7 @@ namespace blueprint * @throws EcmascriptEngine::Error in the event of an error */ template - juce::var invoke (const juce::String& name, T... args); + juce::var invoke(const juce::String& name, T... args); //============================================================================== /** Resets the internal Duktape context, clearing the value stack and destroying native callbacks. */ @@ -155,16 +155,16 @@ namespace blueprint std::unique_ptr mPimpl; //============================================================================== - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (EcmascriptEngine) + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(EcmascriptEngine) }; //============================================================================== template - juce::var EcmascriptEngine::invoke (const juce::String& name, T... args) + juce::var EcmascriptEngine::invoke(const juce::String& name, T... args) { // Pack the args and push them to the alternate `invoke` implementation - std::vector vargs { args... }; + std::vector vargs{ args... }; return invoke(name, vargs); } -} +} // namespace blueprint diff --git a/blueprint/core/blueprint_FileWatcher.h b/blueprint/core/blueprint_FileWatcher.h index 464d6518..20c7ab7e 100644 --- a/blueprint/core/blueprint_FileWatcher.h +++ b/blueprint/core/blueprint_FileWatcher.h @@ -9,10 +9,8 @@ #pragma once - namespace blueprint { - //============================================================================== /** Helper class which watches files for changes and triggers a user supplied * callback in thte event of a file change. @@ -22,13 +20,13 @@ namespace blueprint public: using FileChangedCallback = std::function; - explicit FileWatcher (FileChangedCallback && callback) + explicit FileWatcher(FileChangedCallback&& callback) : onFileChanged(std::move(callback)) {} void start() { startTimer(50); } void stop() { stopTimer(); } - void watch (const juce::File& f) + void watch(const juce::File& f) { JUCE_ASSERT_MESSAGE_THREAD @@ -92,8 +90,8 @@ namespace blueprint // insertion order retained. In the event of a file change, we want to // re-evaluate all bundles within the cleaned engine in the same order // we started with. - std::map watchedFiles; - FileChangedCallback onFileChanged; + std::map watchedFiles; + FileChangedCallback onFileChanged; }; -} +} // namespace blueprint diff --git a/blueprint/core/blueprint_GenericEditor.cpp b/blueprint/core/blueprint_GenericEditor.cpp index 0f341084..bc7456a9 100644 --- a/blueprint/core/blueprint_GenericEditor.cpp +++ b/blueprint/core/blueprint_GenericEditor.cpp @@ -9,19 +9,14 @@ #pragma once - namespace blueprint { - //============================================================================== - BlueprintGenericEditor::BlueprintGenericEditor (juce::AudioProcessor& proc, const juce::File& bundle) - : juce::AudioProcessorEditor (proc) - , engine(std::make_shared()) - , appRoot(engine) - , harness(appRoot) + BlueprintGenericEditor::BlueprintGenericEditor(juce::AudioProcessor& proc, const juce::File& bundle) + : juce::AudioProcessorEditor(proc), engine(std::make_shared()), appRoot(engine), harness(appRoot) { // Sanity check - jassert (bundle.existsAsFile()); + jassert(bundle.existsAsFile()); bundleFile = bundle; // Now we set up parameter listeners and register their current values. @@ -31,7 +26,8 @@ namespace blueprint for (auto& p : params) { // Store the parameter ID for easy lookup in gesture lambdas - if (auto paramWithID = dynamic_cast(p)) { + if (auto paramWithID = dynamic_cast(p)) + { parameters.emplace(paramWithID->paramID, p); } @@ -71,7 +67,7 @@ namespace blueprint } //============================================================================== - void BlueprintGenericEditor::parameterValueChanged (int parameterIndex, float newValue) + void BlueprintGenericEditor::parameterValueChanged(int parameterIndex, float newValue) { // This callback often runs on the realtime thread. To avoid any blocking // or non-deterministic operations, we simply set some atomic values in our @@ -81,7 +77,7 @@ namespace blueprint paramReadouts[parameterIndex].dirty = true; } - void BlueprintGenericEditor::parameterGestureChanged (int, bool) + void BlueprintGenericEditor::parameterGestureChanged(int, bool) { // Our generic editor doesn't do anything with this information yet, but // we'll happily take a pull request if you need something here :). @@ -115,8 +111,7 @@ namespace blueprint id, defaultValue, value, - stringValue - ); + stringValue); } } } @@ -140,32 +135,29 @@ namespace blueprint engine->registerNativeMethod( "beginParameterChangeGesture", [this](const juce::var::NativeFunctionArgs& args) { - if (auto it = parameters.find (args.arguments[0].toString()); it != parameters.cend()) + if (auto it = parameters.find(args.arguments[0].toString()); it != parameters.cend()) it->second->beginChangeGesture(); return juce::var::undefined(); - } - ); + }); engine->registerNativeMethod( "setParameterValueNotifyingHost", [this](const juce::var::NativeFunctionArgs& args) { - if (auto it = parameters.find (args.arguments[0].toString()); it != parameters.cend()) + if (auto it = parameters.find(args.arguments[0].toString()); it != parameters.cend()) it->second->setValueNotifyingHost(args.arguments[1]); return juce::var::undefined(); - } - ); + }); engine->registerNativeMethod( "endParameterChangeGesture", [this](const juce::var::NativeFunctionArgs& args) { - if (auto it = parameters.find (args.arguments[0].toString()); it != parameters.cend()) + if (auto it = parameters.find(args.arguments[0].toString()); it != parameters.cend()) it->second->endChangeGesture(); return juce::var::undefined(); - } - ); + }); } void BlueprintGenericEditor::afterBundleEvaluated() @@ -175,4 +167,4 @@ namespace blueprint parameterValueChanged(p->getParameterIndex(), p->getValue()); } -} +} // namespace blueprint diff --git a/blueprint/core/blueprint_GenericEditor.h b/blueprint/core/blueprint_GenericEditor.h index 9c44688e..ecd3f0cf 100644 --- a/blueprint/core/blueprint_GenericEditor.h +++ b/blueprint/core/blueprint_GenericEditor.h @@ -12,10 +12,8 @@ #include "blueprint_AppHarness.h" #include "blueprint_ReactApplicationRoot.h" - namespace blueprint { - //============================================================================== /** The BlueprintGenericEditor is a default AudioProcessorEditor with preinstalled functionality * for working with Blueprint. @@ -25,19 +23,19 @@ namespace blueprint * development tools. */ class BlueprintGenericEditor - : public juce::AudioProcessorEditor - , public juce::AudioProcessorParameter::Listener - , public juce::Timer + : public juce::AudioProcessorEditor, + public juce::AudioProcessorParameter::Listener, + public juce::Timer { public: //============================================================================== - BlueprintGenericEditor (juce::AudioProcessor&, const juce::File&); + BlueprintGenericEditor(juce::AudioProcessor&, const juce::File&); ~BlueprintGenericEditor() override; //============================================================================== /** Implement the AudioProcessorParameter::Listener interface. */ - void parameterValueChanged (int parameterIndex, float newValue) override; - void parameterGestureChanged (int parameterIndex, bool gestureIsStarting) override; + void parameterValueChanged(int parameterIndex, float newValue) override; + void parameterGestureChanged(int parameterIndex, bool gestureIsStarting) override; //============================================================================== /** Override the timer interface. */ @@ -46,7 +44,7 @@ namespace blueprint //============================================================================== /** Override the component interface. */ void resized() override; - void paint (juce::Graphics&) override; + void paint(juce::Graphics&) override; private: //============================================================================== @@ -55,15 +53,15 @@ namespace blueprint void afterBundleEvaluated(); //============================================================================== - std::shared_ptr engine; - ReactApplicationRoot appRoot; - AppHarness harness; + std::shared_ptr engine; + ReactApplicationRoot appRoot; + AppHarness harness; - juce::File bundleFile; + juce::File bundleFile; // We keep a map of the parameter IDs and their associated parameter pointers // to have a quick lookup in beforeBundleEvaluated where lambdas are called - // with a param ID + // with a param ID std::map parameters; //============================================================================== @@ -71,13 +69,15 @@ namespace blueprint // propagated to the user interface. During parameter value changes on the // realtime thread, we capture the values in this array of structs, then at // 30Hz propagate the value changes via dispatching events to the jsui. - struct ParameterReadout { + struct ParameterReadout + { std::atomic value = 0.0; std::atomic dirty = false; ParameterReadout() = default; - ParameterReadout(const ParameterReadout& other) { + ParameterReadout(const ParameterReadout& other) + { value = other.value.load(); dirty = other.dirty.load(); } @@ -86,7 +86,7 @@ namespace blueprint std::vector paramReadouts; //============================================================================== - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BlueprintGenericEditor) + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(BlueprintGenericEditor) }; -} +} // namespace blueprint diff --git a/blueprint/core/blueprint_ImageView.h b/blueprint/core/blueprint_ImageView.h index 34ce4d29..b01fdadd 100644 --- a/blueprint/core/blueprint_ImageView.h +++ b/blueprint/core/blueprint_ImageView.h @@ -11,7 +11,6 @@ #include "blueprint_View.h" - namespace blueprint { namespace @@ -19,14 +18,12 @@ namespace blueprint // juce::URL::isWellFormed is currently not a complete // implementation, so we have this slightly more robust check // for now. - bool isWellFormedURL(const juce::URL &url) + bool isWellFormedURL(const juce::URL& url) { - return url.isWellFormed() && - url.getScheme().isNotEmpty() && - !url.toString(false).startsWith("data"); + return url.isWellFormed() && url.getScheme().isNotEmpty() && ! url.toString(false).startsWith("data"); } - } + } // namespace //============================================================================== /** The ImageView class is a core view for drawing images within Blueprint's @@ -36,21 +33,21 @@ namespace blueprint { public: //============================================================================== - static inline juce::Identifier sourceProp = "source"; + static inline juce::Identifier sourceProp = "source"; static inline juce::Identifier placementProp = "placement"; //============================================================================== ImageView() = default; //============================================================================== - void setProperty (const juce::Identifier& name, const juce::var& value) override + void setProperty(const juce::Identifier& name, const juce::var& value) override { View::setProperty(name, value); if (name == sourceProp) { - const juce::String source = value.toString(); - const juce::URL sourceURL = source; + const juce::String source = value.toString(); + const juce::URL sourceURL = source; if (isWellFormedURL(sourceURL)) { @@ -67,42 +64,40 @@ namespace blueprint else // If not a URL treat source prop as inline SVG/Image data { drawable = std::unique_ptr( - juce::Drawable::createFromImageData( - source.toRawUTF8(), - source.getNumBytesAsUTF8() - ) - ); + juce::Drawable::createFromImageData( + source.toRawUTF8(), + source.getNumBytesAsUTF8())); } } } //============================================================================== - void paint (juce::Graphics& g) override + void paint(juce::Graphics& g) override { View::paint(g); const float opacity = props.getWithDefault(opacityProp, 1.0f); // Without a specified placement, we just draw the drawable. - if (!props.contains(placementProp)) + if (! props.contains(placementProp)) return drawable->draw(g, opacity); // Otherwise we map placement strings to the appropriate flags const int existingFlags = props[placementProp]; - const juce::RectanglePlacement placement (existingFlags); + const juce::RectanglePlacement placement(existingFlags); drawable->drawWithin(g, getLocalBounds().toFloat(), placement, opacity); } private: //============================================================================== - juce::Image loadImageFromURL(const juce::URL &url) const + juce::Image loadImageFromURL(const juce::URL& url) const { if (url.isLocalFile()) { const juce::File imageFile = url.getLocalFile(); - if (!imageFile.existsAsFile()) + if (! imageFile.existsAsFile()) { const juce::String errorString = "Image file does not exist: " + imageFile.getFullPathName(); throw std::logic_error(errorString.toStdString()); @@ -158,14 +153,14 @@ namespace blueprint const auto base64EncodedData = source.substring(commaIndex + 1); juce::MemoryOutputStream outStream{}; - if(!juce::Base64::convertFromBase64(outStream, base64EncodedData)) + if (! juce::Base64::convertFromBase64(outStream, base64EncodedData)) { throw std::runtime_error("Image failed to convert data url."); } - juce::MemoryInputStream inputStream (outStream.getData(), outStream.getDataSize(), false); + juce::MemoryInputStream inputStream(outStream.getData(), outStream.getDataSize(), false); - const auto mimeType = source.substring(5,semiIndex); + const auto mimeType = source.substring(5, semiIndex); auto fmt = prepareImageFormat(mimeType); if (fmt == nullptr) @@ -173,7 +168,7 @@ namespace blueprint throw std::runtime_error("Unsupported format."); } - if (!fmt->canUnderstand(inputStream)) + if (! fmt->canUnderstand(inputStream)) { throw std::runtime_error("Cannot understand the image."); } @@ -205,7 +200,6 @@ namespace blueprint std::unique_ptr drawable; //============================================================================== - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ImageView) - + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ImageView) }; -} +} // namespace blueprint diff --git a/blueprint/core/blueprint_RawTextView.h b/blueprint/core/blueprint_RawTextView.h index c84476f7..07ad8e4a 100644 --- a/blueprint/core/blueprint_RawTextView.h +++ b/blueprint/core/blueprint_RawTextView.h @@ -11,10 +11,8 @@ #include "blueprint_View.h" - namespace blueprint { - //============================================================================== /** The RawTextView class is more or less a wrapper around a string that asserts itself as a leaf node in the tree by refusing a resize and painting nothing. @@ -34,13 +32,14 @@ namespace blueprint RawTextView(const juce::String& text) : _text(text) {} //============================================================================== - void setProperty (const juce::Identifier&, const juce::var&) override + void setProperty(const juce::Identifier&, const juce::var&) override { throw std::logic_error("A RawTextView can't receive properties."); } //============================================================================== - void setText (const juce::String& text) { + void setText(const juce::String& text) + { _text = text; } @@ -54,7 +53,7 @@ namespace blueprint juce::String _text; //============================================================================== - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RawTextView) + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(RawTextView) }; -} +} // namespace blueprint diff --git a/blueprint/core/blueprint_ReactApplicationRoot.cpp b/blueprint/core/blueprint_ReactApplicationRoot.cpp index 231e676e..6ab4ff8c 100644 --- a/blueprint/core/blueprint_ReactApplicationRoot.cpp +++ b/blueprint/core/blueprint_ReactApplicationRoot.cpp @@ -11,13 +11,10 @@ #include "blueprint_ReactApplicationRoot.h" - namespace blueprint { - ReactApplicationRoot::ReactApplicationRoot(std::shared_ptr ee) - : viewManager(this) - , engine(ee) + : viewManager(this), engine(ee) { JUCE_ASSERT_MESSAGE_THREAD jassert(ee != nullptr); @@ -34,35 +31,35 @@ namespace blueprint : ReactApplicationRoot(std::make_shared()) {} //============================================================================== - juce::var ReactApplicationRoot::createViewInstance (const juce::String& viewType) + juce::var ReactApplicationRoot::createViewInstance(const juce::String& viewType) { return juce::var(viewManager.createViewInstance(viewType)); } - juce::var ReactApplicationRoot::createTextViewInstance (const juce::String& textValue) + juce::var ReactApplicationRoot::createTextViewInstance(const juce::String& textValue) { return juce::var(viewManager.createTextViewInstance(textValue)); } - juce::var ReactApplicationRoot::setViewProperty (const ViewId viewId, const juce::String& name, const juce::var& value) + juce::var ReactApplicationRoot::setViewProperty(const ViewId viewId, const juce::String& name, const juce::var& value) { viewManager.setViewProperty(viewId, name, value); return juce::var::undefined(); } - juce::var ReactApplicationRoot::setRawTextValue (const ViewId viewId, const juce::String& value) + juce::var ReactApplicationRoot::setRawTextValue(const ViewId viewId, const juce::String& value) { viewManager.setRawTextValue(viewId, value); return juce::var::undefined(); } - juce::var ReactApplicationRoot::insertChild (const ViewId parentId, const ViewId childId, int index) + juce::var ReactApplicationRoot::insertChild(const ViewId parentId, const ViewId childId, int index) { viewManager.insertChild(parentId, childId, index); return juce::var::undefined(); } - juce::var ReactApplicationRoot::removeChild (const ViewId parentId, const ViewId childId) + juce::var ReactApplicationRoot::removeChild(const ViewId parentId, const ViewId childId) { viewManager.removeChild(parentId, childId); return juce::var::undefined(); @@ -182,10 +179,9 @@ namespace blueprint engine->registerNativeProperty(ns, juce::JSON::parse("{}")); - engine->registerNativeMethod(ns, "invokeViewMethod", [this](const juce::var::NativeFunctionArgs& args) -> juce::var - { + engine->registerNativeMethod(ns, "invokeViewMethod", [this](const juce::var::NativeFunctionArgs& args) -> juce::var { jassert(args.numArguments >= 2); - const ViewId viewId = args.arguments[0]; + const ViewId viewId = args.arguments[0]; const juce::String method = args.arguments[1]; const juce::var::NativeFunctionArgs methodArgs(args.thisObject, args.arguments + 2, args.numArguments - 2); @@ -202,4 +198,4 @@ namespace blueprint addMethodBinding<0>(ns, "resetAfterCommit", &ReactApplicationRoot::resetAfterCommit); } -} +} // namespace blueprint diff --git a/blueprint/core/blueprint_ReactApplicationRoot.h b/blueprint/core/blueprint_ReactApplicationRoot.h index 8e54f047..9e02b990 100644 --- a/blueprint/core/blueprint_ReactApplicationRoot.h +++ b/blueprint/core/blueprint_ReactApplicationRoot.h @@ -14,10 +14,8 @@ #include "blueprint_View.h" #include "blueprint_ViewManager.h" - namespace blueprint { - //============================================================================== /** The ReactApplicationRoot class is the primary point of coordination between * the React.js reconciler and the native View heirarchy. @@ -42,12 +40,12 @@ namespace blueprint //============================================================================== /** The main rendering interface. */ - juce::var createViewInstance (const juce::String& viewType); - juce::var createTextViewInstance (const juce::String& textValue); - juce::var setViewProperty (const ViewId viewId, const juce::String& name, const juce::var& value); - juce::var setRawTextValue (const ViewId viewId, const juce::String& value); - juce::var insertChild (const ViewId parentId, const ViewId childId, int index); - juce::var removeChild (const ViewId parentId, const ViewId childId); + juce::var createViewInstance(const juce::String& viewType); + juce::var createTextViewInstance(const juce::String& textValue); + juce::var setViewProperty(const ViewId viewId, const juce::String& name, const juce::var& value); + juce::var setRawTextValue(const ViewId viewId, const juce::String& value); + juce::var insertChild(const ViewId parentId, const ViewId childId, int index); + juce::var removeChild(const ViewId parentId, const ViewId childId); juce::var getRootInstanceId(); juce::var resetAfterCommit(); @@ -76,7 +74,7 @@ namespace blueprint /** Dispatches an event through Blueprint's EventBridge. */ template - void dispatchEvent (const juce::String& eventType, T... args) + void dispatchEvent(const juce::String& eventType, T... args) { JUCE_ASSERT_MESSAGE_THREAD @@ -86,16 +84,19 @@ namespace blueprint if (errorText) return; - try { + try + { engine->invoke("__BlueprintNative__.dispatchEvent", eventType, std::forward(args)...); - } catch (const EcmascriptEngine::Error& err) { + } + catch (const EcmascriptEngine::Error& err) + { handleRuntimeError(err); } } /** Dispatches a view event through Blueprint's internal event replayer. */ template - void dispatchViewEvent (T... args) + void dispatchViewEvent(T... args) { JUCE_ASSERT_MESSAGE_THREAD @@ -105,9 +106,12 @@ namespace blueprint if (errorText) return; - try { + try + { engine->invoke("__BlueprintNative__.dispatchViewEvent", std::forward(args)...); - } catch (const EcmascriptEngine::Error& err) { + } + catch (const EcmascriptEngine::Error& err) + { handleRuntimeError(err); } } @@ -129,40 +133,45 @@ namespace blueprint private: //============================================================================== template - juce::var invokeFromNativeFunction (MethodType method, const juce::var::NativeFunctionArgs& args) + juce::var invokeFromNativeFunction(MethodType method, const juce::var::NativeFunctionArgs& args) { - static_assert (NumParams <= 4); + static_assert(NumParams <= 4); if (args.numArguments != NumParams) return juce::var::undefined(); - if constexpr (NumParams == 0) return (this->*method)(); - if constexpr (NumParams == 1) return (this->*method)(args.arguments[0]); - if constexpr (NumParams == 2) return (this->*method)(args.arguments[0], args.arguments[1]); - if constexpr (NumParams == 3) return (this->*method)(args.arguments[0], args.arguments[1], args.arguments[2]); - if constexpr (NumParams == 4) return (this->*method)(args.arguments[0], args.arguments[1], args.arguments[2], args.arguments[3]); + if constexpr (NumParams == 0) + return (this->*method)(); + if constexpr (NumParams == 1) + return (this->*method)(args.arguments[0]); + if constexpr (NumParams == 2) + return (this->*method)(args.arguments[0], args.arguments[1]); + if constexpr (NumParams == 3) + return (this->*method)(args.arguments[0], args.arguments[1], args.arguments[2]); + if constexpr (NumParams == 4) + return (this->*method)(args.arguments[0], args.arguments[1], args.arguments[2], args.arguments[3]); return {}; } template - void addMethodBinding (const char* ns, const char* name, MethodType method) { + void addMethodBinding(const char* ns, const char* name, MethodType method) + { engine->registerNativeMethod( ns, name, - [this, method] (const juce::var::NativeFunctionArgs& args) -> juce::var { + [this, method](const juce::var::NativeFunctionArgs& args) -> juce::var { return invokeFromNativeFunction(method, args); - } - ); + }); } //============================================================================== ViewManager viewManager; - std::shared_ptr engine; + std::shared_ptr engine; std::unique_ptr errorText; //============================================================================== - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ReactApplicationRoot) + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ReactApplicationRoot) }; -} +} // namespace blueprint diff --git a/blueprint/core/blueprint_ScrollView.cpp b/blueprint/core/blueprint_ScrollView.cpp index 4f3a116a..6d7bdd3c 100644 --- a/blueprint/core/blueprint_ScrollView.cpp +++ b/blueprint/core/blueprint_ScrollView.cpp @@ -20,7 +20,7 @@ namespace blueprint obj->setProperty("scrollLeft", scrollLeftPosition); return obj.get(); } - } + } // namespace detail //============================================================================== ScrollView::ScrollView() @@ -29,8 +29,7 @@ namespace blueprint // This is prop configurable startTimerHz(30); - viewport.onAreaChanged([this](const juce::Rectangle& area) - { + viewport.onAreaChanged([this](const juce::Rectangle& area) { lastScrollEvent.event = detail::makeScrollEventObject(area.getY(), area.getX()); lastScrollEvent.dirty = true; }); @@ -41,17 +40,22 @@ namespace blueprint exportNativeMethods(); } - void ScrollView::setProperty (const juce::Identifier& name, const juce::var& value) + void ScrollView::setProperty(const juce::Identifier& name, const juce::var& value) { View::setProperty(name, value); auto showX = viewport.isHorizontalScrollBarShown(); auto showY = viewport.isVerticalScrollBarShown(); - auto overflowCheck = [](const juce::String& p, const juce::String &v) - { - if (juce::StringRef("scroll") == v) { return true; } - if (juce::StringRef("hidden") == v) { return false; } + auto overflowCheck = [](const juce::String& p, const juce::String& v) { + if (juce::StringRef("scroll") == v) + { + return true; + } + if (juce::StringRef("hidden") == v) + { + return false; + } const juce::String e = "Invalid prop value. Prop '" + p + "' must be a string of 'hidden' or 'scroll'"; throw std::invalid_argument(e.toStdString()); @@ -71,7 +75,7 @@ namespace blueprint if (name == scrollBarWidthProp) { - if (!props[scrollBarWidthProp].isDouble()) + if (! props[scrollBarWidthProp].isDouble()) throw std::invalid_argument("Invalid prop value. Prop \'scollbar-width\' must be a number."); const int thickness = props[scrollBarWidthProp]; @@ -80,7 +84,7 @@ namespace blueprint if (name == scrollbarThumbColorProp) { - if (!props[scrollbarThumbColorProp].isString()) + if (! props[scrollbarThumbColorProp].isString()) throw std::invalid_argument("Invalid prop value. Prop \'scrollbar-thumb-color\' must be a color string."); const auto thumbColor = juce::Colour::fromString(props[scrollbarThumbColorProp].toString()); @@ -90,7 +94,7 @@ namespace blueprint if (name == scrollbarTrackColorProp) { - if (!props[scrollbarTrackColorProp].isString()) + if (! props[scrollbarTrackColorProp].isString()) throw std::invalid_argument("Invalid prop value. Prop \'scrollbar-track-color\' must be a color string."); const auto trackColor = juce::Colour::fromString(props[scrollbarTrackColorProp].toString()); @@ -100,7 +104,7 @@ namespace blueprint if (name == scrollOnDragProp) { - if (!props[scrollOnDragProp].isBool()) + if (! props[scrollOnDragProp].isBool()) throw std::invalid_argument("Invalid prop value. Prop \'scroll-on-drag\' must be a bool."); const bool scrollOnDrag = props[scrollOnDragProp]; @@ -108,16 +112,16 @@ namespace blueprint } } - void ScrollView::addChild (View* childView, int index) + void ScrollView::addChild(View* childView, int index) { - juce::ignoreUnused (index); - jassert (viewport.getViewedComponent() == nullptr); + juce::ignoreUnused(index); + jassert(viewport.getViewedComponent() == nullptr); viewport.setViewedComponent(childView, false); } void ScrollView::resized() { - const auto &bounds = getLocalBounds(); + const auto& bounds = getLocalBounds(); viewport.setBounds(bounds); View::resized(); } @@ -128,7 +132,7 @@ namespace blueprint { if (props.contains(onScrollProp) && props[onScrollProp].isMethod()) { - std::array args { lastScrollEvent.event }; + std::array args{ lastScrollEvent.event }; juce::var::NativeFunctionArgs nfArgs(juce::var(), args.data(), static_cast(args.size())); std::invoke(props[onScrollProp].getNativeFunction(), nfArgs); @@ -141,14 +145,13 @@ namespace blueprint void ScrollView::exportNativeMethods() { - exportMethod("scrollToPosition", [this] (const juce::var::NativeFunctionArgs &args) -> juce::var - { - jassert(args.numArguments == 2); - const int xPos = args.arguments[0]; - const int yPos = args.arguments[1]; - - viewport.setViewPosition(xPos, yPos); - return juce::var::undefined(); - }); + exportMethod("scrollToPosition", [this](const juce::var::NativeFunctionArgs& args) -> juce::var { + jassert(args.numArguments == 2); + const int xPos = args.arguments[0]; + const int yPos = args.arguments[1]; + + viewport.setViewPosition(xPos, yPos); + return juce::var::undefined(); + }); } -} +} // namespace blueprint diff --git a/blueprint/core/blueprint_ScrollView.h b/blueprint/core/blueprint_ScrollView.h index ce1ca8aa..346141b7 100644 --- a/blueprint/core/blueprint_ScrollView.h +++ b/blueprint/core/blueprint_ScrollView.h @@ -13,19 +13,18 @@ namespace blueprint { - //============================================================================== /** The ScrollView class is a core view for scrollable content within Blueprint's layout system. It's basically a proxy component where the appendChild/removeChild methods delegate to a single child juce::Viewport. */ - class ScrollView : public View - , private juce::Timer + class ScrollView : public View, private juce::Timer { //============================================================================== class ScrollViewViewport : public juce::Viewport { using OnAreaChangedCallback = std::function&)>; + public: ScrollViewViewport() = default; @@ -34,21 +33,21 @@ namespace blueprint onAreaChangedCallback = std::move(callback); } - void visibleAreaChanged(const juce::Rectangle &newArea) override + void visibleAreaChanged(const juce::Rectangle& newArea) override { if (onAreaChangedCallback) onAreaChangedCallback(newArea); } private: - OnAreaChangedCallback onAreaChangedCallback; + OnAreaChangedCallback onAreaChangedCallback; }; //============================================================================== struct ScrollEvent { juce::var event = juce::var(); - bool dirty = false; + bool dirty = false; }; //============================================================================== @@ -57,20 +56,20 @@ namespace blueprint //============================================================================== // Props following CSS Scrollbars spec with some omissions/additions. // https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Scrollbars - static inline juce::Identifier overflowXProp = "overflow-x"; - static inline juce::Identifier overflowYProp = "overflow-y"; - static inline juce::Identifier scrollBarWidthProp = "scrollbar-width"; + static inline juce::Identifier overflowXProp = "overflow-x"; + static inline juce::Identifier overflowYProp = "overflow-y"; + static inline juce::Identifier scrollBarWidthProp = "scrollbar-width"; static inline juce::Identifier scrollbarThumbColorProp = "scrollbar-thumb-color"; static inline juce::Identifier scrollbarTrackColorProp = "scrollbar-track-color"; - static inline juce::Identifier scrollOnDragProp = "scroll-on-drag"; - static inline juce::Identifier onScrollProp = "onScroll"; + static inline juce::Identifier scrollOnDragProp = "scroll-on-drag"; + static inline juce::Identifier onScrollProp = "onScroll"; //============================================================================== ScrollView(); //============================================================================== - void setProperty (const juce::Identifier& name, const juce::var& value) override; - void addChild (View* childView, int index = -1) override; + void setProperty(const juce::Identifier& name, const juce::var& value) override; + void addChild(View* childView, int index = -1) override; //============================================================================== void resized() override; @@ -82,10 +81,10 @@ namespace blueprint //============================================================================== ScrollViewViewport viewport; - ScrollEvent lastScrollEvent; + ScrollEvent lastScrollEvent; //============================================================================== - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ScrollView) + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ScrollView) }; -} +} // namespace blueprint diff --git a/blueprint/core/blueprint_ScrollViewContentShadowView.h b/blueprint/core/blueprint_ScrollViewContentShadowView.h index c4c4597f..69976590 100644 --- a/blueprint/core/blueprint_ScrollViewContentShadowView.h +++ b/blueprint/core/blueprint_ScrollViewContentShadowView.h @@ -12,10 +12,8 @@ #include "blueprint_ShadowView.h" #include "blueprint_View.h" - namespace blueprint { - //============================================================================== /** The ScrollViewContentShadowView extends a ShadowView to provide specialized * behavior for flushing layout bounds to the content element of a ScrolLView. @@ -49,7 +47,7 @@ namespace blueprint private: //============================================================================== - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ScrollViewContentShadowView) + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ScrollViewContentShadowView) }; -} +} // namespace blueprint diff --git a/blueprint/core/blueprint_ShadowView.cpp b/blueprint/core/blueprint_ShadowView.cpp index 1f748d1a..8b819fa7 100644 --- a/blueprint/core/blueprint_ShadowView.cpp +++ b/blueprint/core/blueprint_ShadowView.cpp @@ -9,24 +9,23 @@ namespace blueprint { - namespace { //============================================================================== - std::unordered_map ValidDirectionValues { + std::unordered_map ValidDirectionValues{ { YGDirectionToString(YGDirectionInherit), YGDirectionInherit }, { YGDirectionToString(YGDirectionLTR), YGDirectionLTR }, { YGDirectionToString(YGDirectionRTL), YGDirectionRTL }, }; - std::unordered_map ValidFlexDirectionValues { + std::unordered_map ValidFlexDirectionValues{ { YGFlexDirectionToString(YGFlexDirectionColumn), YGFlexDirectionColumn }, { YGFlexDirectionToString(YGFlexDirectionColumnReverse), YGFlexDirectionColumnReverse }, { YGFlexDirectionToString(YGFlexDirectionRow), YGFlexDirectionRow }, { YGFlexDirectionToString(YGFlexDirectionRowReverse), YGFlexDirectionRowReverse }, }; - std::unordered_map ValidJustifyValues { + std::unordered_map ValidJustifyValues{ { YGJustifyToString(YGJustifyFlexStart), YGJustifyFlexStart }, { YGJustifyToString(YGJustifyCenter), YGJustifyCenter }, { YGJustifyToString(YGJustifyFlexEnd), YGJustifyFlexEnd }, @@ -34,7 +33,7 @@ namespace blueprint { YGJustifyToString(YGJustifySpaceAround), YGJustifySpaceAround }, }; - std::unordered_map ValidAlignValues { + std::unordered_map ValidAlignValues{ { YGAlignToString(YGAlignAuto), YGAlignAuto }, { YGAlignToString(YGAlignFlexStart), YGAlignFlexStart }, { YGAlignToString(YGAlignCenter), YGAlignCenter }, @@ -45,98 +44,100 @@ namespace blueprint { YGAlignToString(YGAlignSpaceAround), YGAlignSpaceAround }, }; - std::unordered_map ValidPositionTypeValues { + std::unordered_map ValidPositionTypeValues{ { YGPositionTypeToString(YGPositionTypeRelative), YGPositionTypeRelative }, { YGPositionTypeToString(YGPositionTypeAbsolute), YGPositionTypeAbsolute }, }; - std::unordered_map ValidFlexWrapValues { + std::unordered_map ValidFlexWrapValues{ { YGWrapToString(YGWrapNoWrap), YGWrapNoWrap }, { YGWrapToString(YGWrapWrap), YGWrapWrap }, { YGWrapToString(YGWrapWrapReverse), YGWrapWrapReverse }, }; - std::unordered_map ValidOverflowValues { + std::unordered_map ValidOverflowValues{ { YGOverflowToString(YGOverflowVisible), YGOverflowVisible }, { YGOverflowToString(YGOverflowHidden), YGOverflowHidden }, { YGOverflowToString(YGOverflowScroll), YGOverflowScroll }, }; + //============================================================================== + class PropertySetterMap + { + using K = juce::String; + using V = juce::var; + using F = std::function; + std::unordered_map propertySetters; + + public: + PropertySetterMap(std::initializer_list> init) : propertySetters(init) {} + bool call(const K& key, const V& v, YGNodeRef node) const + { + const auto setter = propertySetters.find(key); + if (setter == propertySetters.end()) + { + return false; + } + return setter->second(v, node); + } + }; - //============================================================================== - class PropertySetterMap { - using K = juce::String; - using V = juce::var; - using F = std::function; - std::unordered_map propertySetters; - - public: - PropertySetterMap(std::initializer_list> init): propertySetters(init) {} - bool call(const K& key, const V& v, YGNodeRef node) const { - const auto setter = propertySetters.find(key); - if(setter == propertySetters.end()) { - return false; - } - return setter->second(v, node); - } - }; - - static const PropertySetterMap propertySetters{ - {"direction", getYogaNodeEnumSetter(YGNodeStyleSetDirection, ValidDirectionValues)}, - {"flex-direction", getYogaNodeEnumSetter(YGNodeStyleSetFlexDirection, ValidFlexDirectionValues)}, - {"justify-content", getYogaNodeEnumSetter(YGNodeStyleSetJustifyContent, ValidJustifyValues)}, - {"align-items", getYogaNodeEnumSetter(YGNodeStyleSetAlignItems, ValidAlignValues)}, - {"align-content", getYogaNodeEnumSetter(YGNodeStyleSetAlignContent, ValidAlignValues)}, - {"align-self", getYogaNodeEnumSetter(YGNodeStyleSetAlignSelf, ValidAlignValues)}, - {"position", getYogaNodeEnumSetter(YGNodeStyleSetPositionType, ValidPositionTypeValues)}, - {"flex-wrap", getYogaNodeEnumSetter(YGNodeStyleSetFlexWrap, ValidFlexWrapValues)}, - {"overflow", getYogaNodeEnumSetter(YGNodeStyleSetOverflow, ValidOverflowValues)}, - {"flex", getYogaNodeFloatSetter(YGNodeStyleSetFlex)}, - {"flex-grow", getYogaNodeFloatSetter(YGNodeStyleSetFlexGrow)}, - {"flex-shrink", getYogaNodeFloatSetter(YGNodeStyleSetFlexShrink)}, - {"flex-basis", getYogaNodeDimensionAutoSetter(BP_SPREAD_SETTER_AUTO(YGNodeStyleSetFlexBasis))}, - {"width", getYogaNodeDimensionAutoSetter(BP_SPREAD_SETTER_AUTO(YGNodeStyleSetWidth))}, - {"height", getYogaNodeDimensionAutoSetter(BP_SPREAD_SETTER_AUTO(YGNodeStyleSetHeight))}, - {"min-width", getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetMinWidth))}, - {"min-height", getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetMinHeight))}, - {"max-width", getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetMaxWidth))}, - {"max-height", getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetMaxHeight))}, - {"aspect-ratio", getYogaNodeFloatSetter(YGNodeStyleSetAspectRatio)}, - - {"margin", getYogaNodeDimensionAutoSetter(BP_SPREAD_SETTER_AUTO(YGNodeStyleSetMargin), YGEdgeAll)}, - {juce::String("margin-") + YGEdgeToString(YGEdgeLeft), getYogaNodeDimensionAutoSetter(BP_SPREAD_SETTER_AUTO(YGNodeStyleSetMargin), YGEdgeLeft)}, - {juce::String("margin-") + YGEdgeToString(YGEdgeTop), getYogaNodeDimensionAutoSetter(BP_SPREAD_SETTER_AUTO(YGNodeStyleSetMargin), YGEdgeTop)}, - {juce::String("margin-") + YGEdgeToString(YGEdgeRight), getYogaNodeDimensionAutoSetter(BP_SPREAD_SETTER_AUTO(YGNodeStyleSetMargin), YGEdgeRight)}, - {juce::String("margin-") + YGEdgeToString(YGEdgeBottom), getYogaNodeDimensionAutoSetter(BP_SPREAD_SETTER_AUTO(YGNodeStyleSetMargin), YGEdgeBottom)}, - {juce::String("margin-") + YGEdgeToString(YGEdgeStart), getYogaNodeDimensionAutoSetter(BP_SPREAD_SETTER_AUTO(YGNodeStyleSetMargin), YGEdgeStart)}, - {juce::String("margin-") + YGEdgeToString(YGEdgeEnd), getYogaNodeDimensionAutoSetter(BP_SPREAD_SETTER_AUTO(YGNodeStyleSetMargin), YGEdgeEnd)}, - {juce::String("margin-") + YGEdgeToString(YGEdgeHorizontal), getYogaNodeDimensionAutoSetter(BP_SPREAD_SETTER_AUTO(YGNodeStyleSetMargin), YGEdgeHorizontal)}, - {juce::String("margin-") + YGEdgeToString(YGEdgeVertical), getYogaNodeDimensionAutoSetter(BP_SPREAD_SETTER_AUTO(YGNodeStyleSetMargin), YGEdgeLeft)}, - {juce::String("margin-") + YGEdgeToString(YGEdgeAll), getYogaNodeDimensionAutoSetter(BP_SPREAD_SETTER_AUTO(YGNodeStyleSetMargin), YGEdgeAll)}, - - {"padding", getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetPadding), YGEdgeAll)}, - {juce::String("padding-") + YGEdgeToString(YGEdgeLeft), getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetPadding), YGEdgeLeft)}, - {juce::String("padding-") + YGEdgeToString(YGEdgeTop), getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetPadding), YGEdgeTop)}, - {juce::String("padding-") + YGEdgeToString(YGEdgeRight), getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetPadding), YGEdgeRight)}, - {juce::String("padding-") + YGEdgeToString(YGEdgeBottom), getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetPadding), YGEdgeBottom)}, - {juce::String("padding-") + YGEdgeToString(YGEdgeStart), getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetPadding), YGEdgeStart)}, - {juce::String("padding-") + YGEdgeToString(YGEdgeEnd), getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetPadding), YGEdgeEnd)}, - {juce::String("padding-") + YGEdgeToString(YGEdgeHorizontal), getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetPadding), YGEdgeHorizontal)}, - {juce::String("padding-") + YGEdgeToString(YGEdgeVertical), getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetPadding), YGEdgeLeft)}, - {juce::String("margin-") + YGEdgeToString(YGEdgeAll), getYogaNodeDimensionAutoSetter(BP_SPREAD_SETTER_AUTO(YGNodeStyleSetMargin), YGEdgeAll)}, - - {YGEdgeToString(YGEdgeLeft), getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetPosition), YGEdgeLeft)}, - {YGEdgeToString(YGEdgeTop), getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetPosition), YGEdgeTop)}, - {YGEdgeToString(YGEdgeRight), getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetPosition), YGEdgeRight)}, - {YGEdgeToString(YGEdgeBottom), getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetPosition), YGEdgeBottom)}, - }; - } + static const PropertySetterMap propertySetters{ + { "direction", getYogaNodeEnumSetter(YGNodeStyleSetDirection, ValidDirectionValues) }, + { "flex-direction", getYogaNodeEnumSetter(YGNodeStyleSetFlexDirection, ValidFlexDirectionValues) }, + { "justify-content", getYogaNodeEnumSetter(YGNodeStyleSetJustifyContent, ValidJustifyValues) }, + { "align-items", getYogaNodeEnumSetter(YGNodeStyleSetAlignItems, ValidAlignValues) }, + { "align-content", getYogaNodeEnumSetter(YGNodeStyleSetAlignContent, ValidAlignValues) }, + { "align-self", getYogaNodeEnumSetter(YGNodeStyleSetAlignSelf, ValidAlignValues) }, + { "position", getYogaNodeEnumSetter(YGNodeStyleSetPositionType, ValidPositionTypeValues) }, + { "flex-wrap", getYogaNodeEnumSetter(YGNodeStyleSetFlexWrap, ValidFlexWrapValues) }, + { "overflow", getYogaNodeEnumSetter(YGNodeStyleSetOverflow, ValidOverflowValues) }, + { "flex", getYogaNodeFloatSetter(YGNodeStyleSetFlex) }, + { "flex-grow", getYogaNodeFloatSetter(YGNodeStyleSetFlexGrow) }, + { "flex-shrink", getYogaNodeFloatSetter(YGNodeStyleSetFlexShrink) }, + { "flex-basis", getYogaNodeDimensionAutoSetter(BP_SPREAD_SETTER_AUTO(YGNodeStyleSetFlexBasis)) }, + { "width", getYogaNodeDimensionAutoSetter(BP_SPREAD_SETTER_AUTO(YGNodeStyleSetWidth)) }, + { "height", getYogaNodeDimensionAutoSetter(BP_SPREAD_SETTER_AUTO(YGNodeStyleSetHeight)) }, + { "min-width", getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetMinWidth)) }, + { "min-height", getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetMinHeight)) }, + { "max-width", getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetMaxWidth)) }, + { "max-height", getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetMaxHeight)) }, + { "aspect-ratio", getYogaNodeFloatSetter(YGNodeStyleSetAspectRatio) }, + + { "margin", getYogaNodeDimensionAutoSetter(BP_SPREAD_SETTER_AUTO(YGNodeStyleSetMargin), YGEdgeAll) }, + { juce::String("margin-") + YGEdgeToString(YGEdgeLeft), getYogaNodeDimensionAutoSetter(BP_SPREAD_SETTER_AUTO(YGNodeStyleSetMargin), YGEdgeLeft) }, + { juce::String("margin-") + YGEdgeToString(YGEdgeTop), getYogaNodeDimensionAutoSetter(BP_SPREAD_SETTER_AUTO(YGNodeStyleSetMargin), YGEdgeTop) }, + { juce::String("margin-") + YGEdgeToString(YGEdgeRight), getYogaNodeDimensionAutoSetter(BP_SPREAD_SETTER_AUTO(YGNodeStyleSetMargin), YGEdgeRight) }, + { juce::String("margin-") + YGEdgeToString(YGEdgeBottom), getYogaNodeDimensionAutoSetter(BP_SPREAD_SETTER_AUTO(YGNodeStyleSetMargin), YGEdgeBottom) }, + { juce::String("margin-") + YGEdgeToString(YGEdgeStart), getYogaNodeDimensionAutoSetter(BP_SPREAD_SETTER_AUTO(YGNodeStyleSetMargin), YGEdgeStart) }, + { juce::String("margin-") + YGEdgeToString(YGEdgeEnd), getYogaNodeDimensionAutoSetter(BP_SPREAD_SETTER_AUTO(YGNodeStyleSetMargin), YGEdgeEnd) }, + { juce::String("margin-") + YGEdgeToString(YGEdgeHorizontal), getYogaNodeDimensionAutoSetter(BP_SPREAD_SETTER_AUTO(YGNodeStyleSetMargin), YGEdgeHorizontal) }, + { juce::String("margin-") + YGEdgeToString(YGEdgeVertical), getYogaNodeDimensionAutoSetter(BP_SPREAD_SETTER_AUTO(YGNodeStyleSetMargin), YGEdgeLeft) }, + { juce::String("margin-") + YGEdgeToString(YGEdgeAll), getYogaNodeDimensionAutoSetter(BP_SPREAD_SETTER_AUTO(YGNodeStyleSetMargin), YGEdgeAll) }, + + { "padding", getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetPadding), YGEdgeAll) }, + { juce::String("padding-") + YGEdgeToString(YGEdgeLeft), getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetPadding), YGEdgeLeft) }, + { juce::String("padding-") + YGEdgeToString(YGEdgeTop), getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetPadding), YGEdgeTop) }, + { juce::String("padding-") + YGEdgeToString(YGEdgeRight), getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetPadding), YGEdgeRight) }, + { juce::String("padding-") + YGEdgeToString(YGEdgeBottom), getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetPadding), YGEdgeBottom) }, + { juce::String("padding-") + YGEdgeToString(YGEdgeStart), getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetPadding), YGEdgeStart) }, + { juce::String("padding-") + YGEdgeToString(YGEdgeEnd), getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetPadding), YGEdgeEnd) }, + { juce::String("padding-") + YGEdgeToString(YGEdgeHorizontal), getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetPadding), YGEdgeHorizontal) }, + { juce::String("padding-") + YGEdgeToString(YGEdgeVertical), getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetPadding), YGEdgeLeft) }, + { juce::String("margin-") + YGEdgeToString(YGEdgeAll), getYogaNodeDimensionAutoSetter(BP_SPREAD_SETTER_AUTO(YGNodeStyleSetMargin), YGEdgeAll) }, + + { YGEdgeToString(YGEdgeLeft), getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetPosition), YGEdgeLeft) }, + { YGEdgeToString(YGEdgeTop), getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetPosition), YGEdgeTop) }, + { YGEdgeToString(YGEdgeRight), getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetPosition), YGEdgeRight) }, + { YGEdgeToString(YGEdgeBottom), getYogaNodeDimensionSetter(BP_SPREAD_SETTER_PERCENT(YGNodeStyleSetPosition), YGEdgeBottom) }, + }; + } // namespace //============================================================================== - bool ShadowView::setProperty (const juce::String& name, const juce::var& newValue) + bool ShadowView::setProperty(const juce::String& name, const juce::var& newValue) { props.set(name, newValue); return propertySetters.call(name, newValue, yogaNode); } -} +} // namespace blueprint diff --git a/blueprint/core/blueprint_ShadowView.h b/blueprint/core/blueprint_ShadowView.h index c2d8e90d..aff75302 100644 --- a/blueprint/core/blueprint_ShadowView.h +++ b/blueprint/core/blueprint_ShadowView.h @@ -16,11 +16,12 @@ namespace blueprint { - - struct BoundsAnimator : public juce::Timer { + struct BoundsAnimator : public juce::Timer + { using StepCallback = std::function)>; - enum class EasingType { + enum class EasingType + { Linear, QuadraticIn, QuadraticOut, @@ -35,32 +36,28 @@ namespace blueprint int frameRate = 45; EasingType easingType = EasingType::Linear; - BoundsAnimator(double durationMs, int frameRateToUse, EasingType et, - juce::Rectangle startRect, juce::Rectangle destRect, - StepCallback cb) - : start(startRect) - , dest(destRect) - , callback(std::move (cb)) - , duration(durationMs) - , frameRate(frameRateToUse) - , easingType(et) + BoundsAnimator(double durationMs, int frameRateToUse, EasingType et, juce::Rectangle startRect, juce::Rectangle destRect, StepCallback cb) + : start(startRect), dest(destRect), callback(std::move(cb)), duration(durationMs), frameRate(frameRateToUse), easingType(et) { startTime = juce::Time::getMillisecondCounterHiRes(); startTimerHz(45); } - ~BoundsAnimator() override { + ~BoundsAnimator() override + { stopTimer(); } - static constexpr float lerp (float a, float b, double t) { return a + (static_cast (t) * (b - a)); } + static constexpr float lerp(float a, float b, double t) { return a + (static_cast(t) * (b - a)); } - void timerCallback() override { + void timerCallback() override + { auto now = juce::Time::getMillisecondCounterHiRes(); double t = std::clamp((now - startTime) / duration, 0.0, 1.0); // Super helpful cheat sheet: https://gist.github.com/gre/1650294 - switch (easingType) { + switch (easingType) + { case EasingType::Linear: break; case EasingType::QuadraticIn: @@ -76,7 +73,8 @@ namespace blueprint break; } - if (t >= 0.9999) { + if (t >= 0.9999) + { callback(dest); stopTimer(); return; @@ -91,56 +89,63 @@ namespace blueprint } }; - template - const auto getYogaNodeFloatSetter(Setter setter, Args... args) { - return [=](const juce::var& value, YGNodeRef node) { - if(value.isDouble()) { - setter(node, args..., (float) value); - return true; - } - return false; - }; + template + const auto getYogaNodeFloatSetter(Setter setter, Args... args) + { + return [=](const juce::var& value, YGNodeRef node) { + if (value.isDouble()) + { + setter(node, args..., (float) value); + return true; + } + return false; + }; } - template - const auto getYogaNodeDimensionSetter(Setter setter, SetterPercent setterPercent, Args... args) { - return [=, floatSetter = getYogaNodeFloatSetter(setter, args...)](const juce::var& value, YGNodeRef node) { - if (floatSetter(value, node)) - return true; - if (value.isString() && value.toString().contains("%")) - { - juce::String strVal = value.toString().retainCharacters("-1234567890."); - setterPercent(node, args..., strVal.getFloatValue()); - return true; - } - setter(node, args..., YGUndefined); - return true; - }; + template + const auto getYogaNodeDimensionSetter(Setter setter, SetterPercent setterPercent, Args... args) + { + return [=, floatSetter = getYogaNodeFloatSetter(setter, args...)](const juce::var& value, YGNodeRef node) { + if (floatSetter(value, node)) + return true; + if (value.isString() && value.toString().contains("%")) + { + juce::String strVal = value.toString().retainCharacters("-1234567890."); + setterPercent(node, args..., strVal.getFloatValue()); + return true; + } + setter(node, args..., YGUndefined); + return true; + }; } - template - const auto getYogaNodeDimensionAutoSetter(Setter setter, SetterPercent setterPercent, SetterAuto setterAuto, Args... args) { - return [=, nonAutoSetter = getYogaNodeDimensionSetter(setter, setterPercent, args...)](const juce::var& value, YGNodeRef node) { - if (value.isString() && value.toString() == "auto") { - setterAuto(node, args...); - return true; - } - return nonAutoSetter(value, node); - }; + template + const auto getYogaNodeDimensionAutoSetter(Setter setter, SetterPercent setterPercent, SetterAuto setterAuto, Args... args) + { + return [=, nonAutoSetter = getYogaNodeDimensionSetter(setter, setterPercent, args...)](const juce::var& value, YGNodeRef node) { + if (value.isString() && value.toString() == "auto") + { + setterAuto(node, args...); + return true; + } + return nonAutoSetter(value, node); + }; } template - const auto getYogaNodeEnumSetter(Setter setter, EnumMap &map) { - return [=](const juce::var& value, YGNodeRef node) { \ - const auto val = map.find(value); - if(val == map.end()) { - // TODO catch further up to add the key at which we tried - // to set this enum property to the message and rethrow - throw std::invalid_argument("Invalid property: " + value.toString().toStdString()); - } - setter(node, val->second); - return true; - }; + const auto getYogaNodeEnumSetter(Setter setter, EnumMap& map) + { + return [=](const juce::var& value, YGNodeRef node) { + const auto val = map.find(value); + if (val == map.end()) + { + // TODO catch further up to add the key at which we tried + // to set this enum property to the message and rethrow + throw std::invalid_argument("Invalid property: " + value.toString().toStdString()); + } + setter(node, val->second); + return true; + }; } //============================================================================== @@ -152,10 +157,10 @@ namespace blueprint { public: //============================================================================== - static const inline juce::Identifier debugProp = "debug"; - static const inline juce::Identifier durationProp = "duration"; - static const inline juce::Identifier easingProp = "easing"; - static const inline juce::Identifier frameRateProp = "frameRate"; + static const inline juce::Identifier debugProp = "debug"; + static const inline juce::Identifier durationProp = "duration"; + static const inline juce::Identifier easingProp = "easing"; + static const inline juce::Identifier frameRateProp = "frameRate"; static const inline juce::Identifier layoutAnimatedProp = "layoutAnimated"; //============================================================================== @@ -172,10 +177,10 @@ namespace blueprint //============================================================================== /** Set a property on the shadow view. */ - virtual bool setProperty (const juce::String& name, const juce::var& newValue); + virtual bool setProperty(const juce::String& name, const juce::var& newValue); /** Adds a child component behind the existing children. */ - virtual void addChild (ShadowView* childView, int index = -1) + virtual void addChild(ShadowView* childView, int index = -1) { if (index == -1) { @@ -184,15 +189,15 @@ namespace blueprint } else { - jassert (juce::isPositiveAndNotGreaterThan(index, YGNodeGetChildCount(yogaNode))); + jassert(juce::isPositiveAndNotGreaterThan(index, YGNodeGetChildCount(yogaNode))); - YGNodeInsertChild(yogaNode, childView->yogaNode, static_cast (index)); + YGNodeInsertChild(yogaNode, childView->yogaNode, static_cast(index)); children.insert(children.begin() + index, childView); } } /** Removes a child component from the children array. */ - virtual void removeChild (ShadowView* childView) + virtual void removeChild(ShadowView* childView) { auto it = std::find(children.begin(), children.end(), childView); @@ -232,9 +237,7 @@ namespace blueprint { #ifdef DEBUG if (props.contains(debugProp)) - YGNodePrint(yogaNode, (YGPrintOptions) (YGPrintOptionsLayout - | YGPrintOptionsStyle - | YGPrintOptionsChildren)); + YGNodePrint(yogaNode, (YGPrintOptions)(YGPrintOptionsLayout | YGPrintOptionsStyle | YGPrintOptionsChildren)); #endif if (props.contains(layoutAnimatedProp)) @@ -251,7 +254,7 @@ namespace blueprint double const frameRate = props[layoutAnimatedProp].getProperty(frameRateProp, 45); int const et = props[layoutAnimatedProp].getProperty(easingProp, 0); - return flushViewLayoutAnimated(durationMs, static_cast (frameRate), static_cast(et)); + return flushViewLayoutAnimated(durationMs, static_cast(frameRate), static_cast(et)); } } @@ -277,15 +280,16 @@ namespace blueprint et, viewCurrentBounds, viewDestinationBounds, - [safeView = juce::Component::SafePointer(view)](auto && stepBounds) { - if (auto* v = safeView.getComponent()) { + [safeView = juce::Component::SafePointer(view)](auto&& stepBounds) { + if (auto* v = safeView.getComponent()) + { v->setFloatBounds(stepBounds); v->setBounds(stepBounds.toNearestInt()); } - } - ); + }); - for (auto& child : children) { + for (auto& child : children) + { child->flushViewLayoutAnimated(durationMs, frameRate, et); } } @@ -301,7 +305,7 @@ namespace blueprint private: //============================================================================== - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ShadowView) + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ShadowView) }; -} +} // namespace blueprint diff --git a/blueprint/core/blueprint_TextShadowView.cpp b/blueprint/core/blueprint_TextShadowView.cpp index 728c6ead..584e00f3 100644 --- a/blueprint/core/blueprint_TextShadowView.cpp +++ b/blueprint/core/blueprint_TextShadowView.cpp @@ -9,16 +9,15 @@ #pragma once - namespace blueprint { - //============================================================================== - YGSize measureTextNode(YGNodeRef node, float width, YGMeasureMode /*widthMode*/, float /*height*/, YGMeasureMode /*heightMode*/) { + YGSize measureTextNode(YGNodeRef node, float width, YGMeasureMode /*widthMode*/, float /*height*/, YGMeasureMode /*heightMode*/) + { auto context = reinterpret_cast(YGNodeGetContext(node)); auto view = dynamic_cast(context->getAssociatedView()); - jassert (view != nullptr); + jassert(view != nullptr); // TODO: This is a bit of an oversimplification. We have a YGMeasureMode which // is one of three things, "undefined", "exact", or "at-most." Here we're kind of @@ -33,4 +32,4 @@ namespace blueprint }; } -} +} // namespace blueprint diff --git a/blueprint/core/blueprint_TextShadowView.h b/blueprint/core/blueprint_TextShadowView.h index 972b025b..c057e0ca 100644 --- a/blueprint/core/blueprint_TextShadowView.h +++ b/blueprint/core/blueprint_TextShadowView.h @@ -12,10 +12,8 @@ #include "blueprint_ShadowView.h" #include "blueprint_View.h" - namespace blueprint { - //============================================================================== /** We use this method to measure the size of a given string so that the * text container knows what size to take. @@ -39,7 +37,7 @@ namespace blueprint //============================================================================== /** Set a property on the shadow view. */ - bool setProperty (const juce::String& name, const juce::var& value) override + bool setProperty(const juce::String& name, const juce::var& value) override { const bool layoutPropertyWasSet = ShadowView::setProperty(name, value); @@ -52,9 +50,9 @@ namespace blueprint } /** Override the default ShadowView behavior to explicitly error. */ - void addChild (ShadowView* childView, int index = -1) override + void addChild(ShadowView* childView, int index = -1) override { - juce::ignoreUnused (index); + juce::ignoreUnused(index); if (childView != nullptr) { @@ -70,7 +68,7 @@ namespace blueprint private: //============================================================================== - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TextShadowView) + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(TextShadowView) }; -} +} // namespace blueprint diff --git a/blueprint/core/blueprint_TextView.h b/blueprint/core/blueprint_TextView.h index ddcc25e6..1a1725ba 100644 --- a/blueprint/core/blueprint_TextView.h +++ b/blueprint/core/blueprint_TextView.h @@ -11,10 +11,8 @@ #include "blueprint_View.h" - namespace blueprint { - //============================================================================== /** The TextView class is a core container abstraction for declaring text components within Blueprint's layout system. @@ -23,16 +21,16 @@ namespace blueprint { public: //============================================================================== - static const inline juce::Identifier colorProp = "color"; + static const inline juce::Identifier colorProp = "color"; - static const inline juce::Identifier fontSizeProp = "font-size"; - static const inline juce::Identifier fontStyleProp = "font-style"; - static const inline juce::Identifier fontFamilyProp = "font-family"; + static const inline juce::Identifier fontSizeProp = "font-size"; + static const inline juce::Identifier fontStyleProp = "font-style"; + static const inline juce::Identifier fontFamilyProp = "font-family"; static const inline juce::Identifier justificationProp = "justification"; static const inline juce::Identifier kerningFactorProp = "kerning-factor"; - static const inline juce::Identifier lineSpacingProp = "line-spacing"; - static const inline juce::Identifier wordWrapProp = "word-wrap"; + static const inline juce::Identifier lineSpacingProp = "line-spacing"; + static const inline juce::Identifier wordWrapProp = "word-wrap"; //============================================================================== TextView() = default; @@ -44,17 +42,17 @@ namespace blueprint float fontHeight = props.getWithDefault(fontSizeProp, 12.0f); int textStyleFlags = props.getWithDefault(fontStyleProp, 0); - juce::Font f (fontHeight); + juce::Font f(fontHeight); if (props.contains(fontFamilyProp)) - f = juce::Font (props[fontFamilyProp], fontHeight, textStyleFlags); + f = juce::Font(props[fontFamilyProp], fontHeight, textStyleFlags); f.setExtraKerningFactor(props.getWithDefault(kerningFactorProp, 0.0)); return f; } /** Constructs a TextLayout from all the children string values. */ - juce::TextLayout getTextLayout (float maxWidth) + juce::TextLayout getTextLayout(float maxWidth) { juce::String hexColor = props.getWithDefault(colorProp, "ff000000"); juce::Colour colour = juce::Colour::fromString(hexColor); @@ -71,7 +69,7 @@ namespace blueprint if (RawTextView* v = dynamic_cast(c)) text += v->getText(); - juce::AttributedString as (text); + juce::AttributedString as(text); juce::TextLayout tl; as.setLineSpacing(props.getWithDefault(lineSpacingProp, 1.0f)); @@ -95,7 +93,6 @@ namespace blueprint default: as.setWordWrap(juce::AttributedString::WordWrap::byWord); break; - } } @@ -104,7 +101,7 @@ namespace blueprint } //============================================================================== - void paint (juce::Graphics& g) override + void paint(juce::Graphics& g) override { auto floatBounds = getLocalBounds().toFloat(); @@ -114,7 +111,7 @@ namespace blueprint private: //============================================================================== - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TextView) + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(TextView) }; -} +} // namespace blueprint diff --git a/blueprint/core/blueprint_View.cpp b/blueprint/core/blueprint_View.cpp index 316297e5..491fa97a 100644 --- a/blueprint/core/blueprint_View.cpp +++ b/blueprint/core/blueprint_View.cpp @@ -7,18 +7,16 @@ ============================================================================== */ - namespace blueprint { - namespace detail { juce::var getMouseEventRelatedTarget(const juce::MouseEvent& e, const blueprint::View& view) { - juce::Component *topParent = view.getTopLevelComponent(); + juce::Component* topParent = view.getTopLevelComponent(); const juce::MouseEvent topRelativeEvent = e.getEventRelativeTo(topParent); - juce::Component *componentUnderMouse = topParent->getComponentAt(topRelativeEvent.x, topRelativeEvent.y); + juce::Component* componentUnderMouse = topParent->getComponentAt(topRelativeEvent.x, topRelativeEvent.y); if (auto v = dynamic_cast(componentUnderMouse)) return v->getViewId(); @@ -28,7 +26,7 @@ namespace blueprint } /** A little helper for DynamicObject construction. */ - juce::var makeViewEventObject (const juce::NamedValueSet& props, const blueprint::View& view) + juce::var makeViewEventObject(const juce::NamedValueSet& props, const blueprint::View& view) { auto* o = new juce::DynamicObject(); @@ -43,29 +41,29 @@ namespace blueprint } /** Another little helper for DynamicObject construction. */ - juce::var makeViewEventObject (const juce::MouseEvent& me, const blueprint::View &view) + juce::var makeViewEventObject(const juce::MouseEvent& me, const blueprint::View& view) { // TODO: Get all of it! - return makeViewEventObject({ - {"x", me.x}, - {"y", me.y}, - {"screenX", me.getScreenX()}, - {"screenY", me.getScreenY()}, - {"relatedTarget", getMouseEventRelatedTarget(me, view)} - }, view); + return makeViewEventObject({ { "x", me.x }, + { "y", me.y }, + { "screenX", me.getScreenX() }, + { "screenY", me.getScreenY() }, + { "relatedTarget", getMouseEventRelatedTarget(me, view) } }, + view); } /** And another little helper for DynamicObject construction. */ - juce::var makeViewEventObject (const juce::KeyPress& ke, const blueprint::View &view) + juce::var makeViewEventObject(const juce::KeyPress& ke, const blueprint::View& view) { // TODO: Get all of it! return makeViewEventObject({ - {"key", juce::String(ke.getTextCharacter())}, - {"keyCode", ke.getKeyCode()}, - }, view); + { "key", juce::String(ke.getTextCharacter()) }, + { "keyCode", ke.getKeyCode() }, + }, + view); } - } + } // namespace detail //============================================================================== ViewId View::getViewId() const @@ -78,20 +76,30 @@ namespace blueprint return _refId; } - void View::setProperty (const juce::Identifier& name, const juce::var& value) + void View::setProperty(const juce::Identifier& name, const juce::var& value) { props.set(name, value); if (name == interceptClickEventsProp) { - switch (static_cast (value)) + switch (static_cast(value)) { - case 0: setInterceptsMouseClicks (false, false); break; - case 1: setInterceptsMouseClicks (true, true); break; - case 2: setInterceptsMouseClicks (true, false); break; - case 3: setInterceptsMouseClicks (false, true); break; - - default: setInterceptsMouseClicks (true, true); break; + case 0: + setInterceptsMouseClicks(false, false); + break; + case 1: + setInterceptsMouseClicks(true, true); + break; + case 2: + setInterceptsMouseClicks(true, false); + break; + case 3: + setInterceptsMouseClicks(false, true); + break; + + default: + setInterceptsMouseClicks(true, true); + break; } } @@ -99,13 +107,13 @@ namespace blueprint setWantsKeyboardFocus(true); if (name == opacityProp) - setAlpha(static_cast (value)); + setAlpha(static_cast(value)); if (name == refIdProp) _refId = juce::Identifier(value.toString()); } - void View::addChild (View* childView, int index) + void View::addChild(View* childView, int index) { // Add the child view to our component heirarchy. addAndMakeVisible(childView, index); @@ -119,27 +127,26 @@ namespace blueprint if (props.contains(transformMatrixProp)) { const juce::var& matrix = props[transformMatrixProp]; - if(matrix.isArray() && matrix.getArray()->size() >= 16) { - const juce::Array &m = *matrix.getArray(); + if (matrix.isArray() && matrix.getArray()->size() >= 16) + { + const juce::Array& m = *matrix.getArray(); - auto cxRelParent = cachedFloatBounds.getX() + cachedFloatBounds.getWidth() * 0.5f; - auto cyRelParent = cachedFloatBounds.getY() + cachedFloatBounds.getHeight() * 0.5f; + auto cxRelParent = cachedFloatBounds.getX() + cachedFloatBounds.getWidth() * 0.5f; + auto cyRelParent = cachedFloatBounds.getY() + cachedFloatBounds.getHeight() * 0.5f; - const auto translateToOrigin = juce::AffineTransform::translation(cxRelParent * -1.0f, cyRelParent * -1.0f); - // set 2d homogeneous matrix using 3d homogeneous matrix - const auto transform = juce::AffineTransform( - m[0], m[1], m[3], - m[4], m[5], m[7] - ); - const auto translateFromOrigin = juce::AffineTransform::translation(cxRelParent, cyRelParent); + const auto translateToOrigin = juce::AffineTransform::translation(cxRelParent * -1.0f, cyRelParent * -1.0f); + // set 2d homogeneous matrix using 3d homogeneous matrix + const auto transform = juce::AffineTransform( + m[0], m[1], m[3], m[4], m[5], m[7]); + const auto translateFromOrigin = juce::AffineTransform::translation(cxRelParent, cyRelParent); - setTransform(translateToOrigin.followedBy(transform).followedBy(translateFromOrigin)); + setTransform(translateToOrigin.followedBy(transform).followedBy(translateFromOrigin)); } } } //============================================================================== - float View::getResolvedLengthProperty (const juce::String& name, float axisLength) + float View::getResolvedLengthProperty(const juce::String& name, float axisLength) { float ret = 0; @@ -161,7 +168,7 @@ namespace blueprint return ret; } - void View::paint (juce::Graphics& g) + void View::paint(juce::Graphics& g) { if (props.contains(borderPathProp)) { @@ -189,7 +196,7 @@ namespace blueprint // line is the exact bounding box then the component clipping makes the corners // appear to have different radii on the interior and exterior of the box. auto borderBounds = getLocalBounds().toFloat().reduced(borderWidth * 0.5f); - auto width = borderBounds.getWidth(); + auto width = borderBounds.getWidth(); auto height = borderBounds.getHeight(); auto minLength = juce::jmin(width, height); float borderRadius = getResolvedLengthProperty(borderRadiusProp.toString(), minLength); @@ -204,7 +211,7 @@ namespace blueprint { juce::Colour c = juce::Colour::fromString(props[backgroundColorProp].toString()); - if (!c.isTransparent()) + if (! c.isTransparent()) g.fillAll(c); } } @@ -215,34 +222,31 @@ namespace blueprint auto w = cachedFloatBounds.getWidth(); auto h = cachedFloatBounds.getHeight(); - dispatchViewEvent("onMeasure", detail::makeViewEventObject({ - {"width", w}, - {"height", h} - }, *this)); + dispatchViewEvent("onMeasure", detail::makeViewEventObject({ { "width", w }, { "height", h } }, *this)); } - void View::mouseDown (const juce::MouseEvent& e) + void View::mouseDown(const juce::MouseEvent& e) { dispatchViewEvent("onMouseDown", detail::makeViewEventObject(e, *this)); } - void View::mouseUp (const juce::MouseEvent& e) + void View::mouseUp(const juce::MouseEvent& e) { dispatchViewEvent("onMouseUp", detail::makeViewEventObject(e, *this)); } - void View::mouseDrag (const juce::MouseEvent& e) + void View::mouseDrag(const juce::MouseEvent& e) { // TODO: mouseDrag isn't a dom event... is it? dispatchViewEvent("onMouseDrag", detail::makeViewEventObject(e, *this)); } - void View::mouseDoubleClick (const juce::MouseEvent& e) + void View::mouseDoubleClick(const juce::MouseEvent& e) { dispatchViewEvent("onMouseDoubleClick", detail::makeViewEventObject(e, *this)); } - bool View::keyPressed (const juce::KeyPress& key) + bool View::keyPressed(const juce::KeyPress& key) { dispatchViewEvent("onKeyPress", detail::makeViewEventObject(key, *this)); @@ -257,21 +261,21 @@ namespace blueprint return true; } - void View::dispatchViewEvent (const juce::String& eventType, const juce::var& e) + void View::dispatchViewEvent(const juce::String& eventType, const juce::var& e) { JUCE_ASSERT_MESSAGE_THREAD - if (auto *parent = findParentComponentOfClass()) + if (auto* parent = findParentComponentOfClass()) parent->dispatchViewEvent(getViewId(), eventType, e); } - void View::exportMethod(const juce::String &method, juce::var::NativeFunction fn) + void View::exportMethod(const juce::String& method, juce::var::NativeFunction fn) { JUCE_ASSERT_MESSAGE_THREAD nativeMethods[method] = std::move(fn); } - juce::var View::invokeMethod(const juce::String &method, const juce::var::NativeFunctionArgs &args) + juce::var View::invokeMethod(const juce::String& method, const juce::var::NativeFunctionArgs& args) { JUCE_ASSERT_MESSAGE_THREAD auto it = nativeMethods.find(method); @@ -281,4 +285,4 @@ namespace blueprint throw std::logic_error("Caller attempted to invoke a non-existent View method"); } -} +} // namespace blueprint diff --git a/blueprint/core/blueprint_View.h b/blueprint/core/blueprint_View.h index 48e94781..9ed2a14f 100644 --- a/blueprint/core/blueprint_View.h +++ b/blueprint/core/blueprint_View.h @@ -13,7 +13,6 @@ namespace blueprint { - // Internally we use a juce::Uuid for uniquely identifying views, but we // need that same identifier to make a transit through JavaScript land // and still match afterwards. So we map our Uuids into a signed 32-bit integer @@ -30,17 +29,17 @@ namespace blueprint public: //============================================================================== static const inline juce::Identifier interceptClickEventsProp = "interceptClickEvents"; - static const inline juce::Identifier onKeyPressProp = "onKeyPress"; - static const inline juce::Identifier opacityProp = "opacity"; - static const inline juce::Identifier refIdProp = "refId"; - static const inline juce::Identifier transformMatrixProp = "transform-matrix"; + static const inline juce::Identifier onKeyPressProp = "onKeyPress"; + static const inline juce::Identifier opacityProp = "opacity"; + static const inline juce::Identifier refIdProp = "refId"; + static const inline juce::Identifier transformMatrixProp = "transform-matrix"; - static const inline juce::Identifier backgroundColorProp = "background-color"; + static const inline juce::Identifier backgroundColorProp = "background-color"; - static const inline juce::Identifier borderColorProp = "border-color"; - static const inline juce::Identifier borderPathProp = "border-path"; - static const inline juce::Identifier borderRadiusProp = "border-radius"; - static const inline juce::Identifier borderWidthProp = "border-width"; + static const inline juce::Identifier borderColorProp = "border-color"; + static const inline juce::Identifier borderPathProp = "border-path"; + static const inline juce::Identifier borderRadiusProp = "border-radius"; + static const inline juce::Identifier borderWidthProp = "border-width"; //============================================================================== View() = default; @@ -54,47 +53,47 @@ namespace blueprint juce::Identifier getRefId() const; /** Set a property on the native view. */ - virtual void setProperty (const juce::Identifier&, const juce::var&); + virtual void setProperty(const juce::Identifier&, const juce::var&); /** Adds a child component behind the existing children. */ - virtual void addChild (View* childView, int index = -1); + virtual void addChild(View* childView, int index = -1); /** Updates the cached float layout bounds from the shadow tree. */ - void setFloatBounds (juce::Rectangle bounds); + void setFloatBounds(juce::Rectangle bounds); //============================================================================== /** Resolves a property to a specific point value or 0 if not present. */ - float getResolvedLengthProperty (const juce::String& name, float axisLength); + float getResolvedLengthProperty(const juce::String& name, float axisLength); /** Override the default Component method with default paint behaviors. */ - void paint (juce::Graphics& g) override; + void paint(juce::Graphics& g) override; //============================================================================== /** Dispatches a resized event to the React application. */ void resized() override; /** Dispatches a mouseDown event to the React application. */ - void mouseDown (const juce::MouseEvent& e) override; + void mouseDown(const juce::MouseEvent& e) override; /** Dispatches a mouseUp event to the React application. */ - void mouseUp (const juce::MouseEvent& e) override; + void mouseUp(const juce::MouseEvent& e) override; /** Dispatches a mouseDrag event to the React application. */ - void mouseDrag (const juce::MouseEvent& e) override; + void mouseDrag(const juce::MouseEvent& e) override; /** Dispatches a mouseDoubleClick event to the React application. */ - void mouseDoubleClick (const juce::MouseEvent& e) override; + void mouseDoubleClick(const juce::MouseEvent& e) override; /** Dispatches a keyPress event to the React application. */ - bool keyPressed (const juce::KeyPress& e) override; + bool keyPressed(const juce::KeyPress& e) override; //============================================================================== /** Invokes, if exists, the respective view event handler. */ - void dispatchViewEvent (const juce::String& eventType, const juce::var& e); + void dispatchViewEvent(const juce::String& eventType, const juce::var& e); //============================================================================== /** Invokes an "exported" native method on the View instance */ - juce::var invokeMethod(const juce::String &method, const juce::var::NativeFunctionArgs &args); + juce::var invokeMethod(const juce::String& method, const juce::var::NativeFunctionArgs& args); protected: //============================================================================== @@ -102,7 +101,7 @@ namespace blueprint * directly from React. This is here to support calling ViewInstance functions * in React via component refs. * */ - void exportMethod(const juce::String &method, juce::var::NativeFunction fn); + void exportMethod(const juce::String& method, juce::var::NativeFunction fn); //============================================================================== juce::NamedValueSet props; @@ -116,7 +115,7 @@ namespace blueprint std::unordered_map nativeMethods; //============================================================================== - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (View) + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(View) }; -} +} // namespace blueprint diff --git a/blueprint/core/blueprint_ViewManager.cpp b/blueprint/core/blueprint_ViewManager.cpp index 10f05f17..213fb08a 100644 --- a/blueprint/core/blueprint_ViewManager.cpp +++ b/blueprint/core/blueprint_ViewManager.cpp @@ -12,28 +12,27 @@ #include "blueprint_ImageView.h" #include "blueprint_ScrollView.h" #include "blueprint_ScrollViewContentShadowView.h" -#include "blueprint_TextView.h" #include "blueprint_TextShadowView.h" +#include "blueprint_TextView.h" namespace blueprint { - namespace { - /** A quick helper for registering view types. */ template struct GenericViewFactory { - ViewManager::ViewPair operator()() { + ViewManager::ViewPair operator()() + { auto view = std::make_unique(); auto shadowView = std::make_unique(view.get()); - return {std::move(view), std::move(shadowView)}; + return { std::move(view), std::move(shadowView) }; } }; - } + } // namespace ViewManager::ViewManager(View* rootView) : rootId(rootView->getViewId()) @@ -49,18 +48,18 @@ namespace blueprint registerViewType("ScrollViewContentView", GenericViewFactory()); } - void ViewManager::registerViewType(const juce::String &typeId, ViewFactory f) + void ViewManager::registerViewType(const juce::String& typeId, ViewFactory f) { // If you hit this jassert, you're trying to register a type which // has already been registered! - jassert (viewFactories.find(typeId) == viewFactories.end()); + jassert(viewFactories.find(typeId) == viewFactories.end()); viewFactories[typeId] = f; } ViewId ViewManager::createViewInstance(const juce::String& viewType) { // We can't create a view instance of a type that hasn't been registered. - jassert (viewFactories.find(viewType) != viewFactories.end()); + jassert(viewFactories.find(viewType) != viewFactories.end()); auto [view, shadowView] = viewFactories[viewType](); ViewId vid = view->getViewId(); @@ -86,9 +85,10 @@ namespace blueprint // ShadowView::setProperty returns true when a layout prop // has been set. Otherwise set on the view and repaint - if(!shadow->setProperty(name, value)) { - view->setProperty(name, value); - view->repaint(); + if (! shadow->setProperty(name, value)) + { + view->setProperty(name, value); + view->repaint(); } } @@ -132,8 +132,8 @@ namespace blueprint // If we're trying to append a child to a text view, it will be raw text // with no accompanying shadow view, and we'll need to mark the parent // TextShadowView dirty before the subsequent layout pass. - jassert (dynamic_cast(childView) != nullptr); - jassert (childShadowView == nullptr); + jassert(dynamic_cast(childView) != nullptr); + jassert(childShadowView == nullptr); parentView->addChild(childView, index); dynamic_cast(parentShadowView)->markDirty(); @@ -184,7 +184,7 @@ namespace blueprint } } - void ViewManager::enumerateChildViewIds (std::vector& ids, View* v) + void ViewManager::enumerateChildViewIds(std::vector& ids, View* v) { for (auto* child : v->getChildren()) { @@ -224,28 +224,28 @@ namespace blueprint shadowViewTable[rootId] = std::make_unique(nh.mapped()->getAssociatedView()); } - juce::var ViewManager::invokeViewMethod(ViewId viewId, const juce::String &method, const juce::var::NativeFunctionArgs &args) + juce::var ViewManager::invokeViewMethod(ViewId viewId, const juce::String& method, const juce::var::NativeFunctionArgs& args) { - if (View *view = getViewHandle(viewId).first) + if (View* view = getViewHandle(viewId).first) return view->invokeMethod(method, args); throw std::logic_error("Caller attempted to invoke method on non-existent View instance"); } - std::pair ViewManager::getViewHandle (ViewId viewId) + std::pair ViewManager::getViewHandle(ViewId viewId) { if (viewId == rootId) - return {shadowViewTable[viewId]->getAssociatedView(), shadowViewTable[viewId].get()}; + return { shadowViewTable[viewId]->getAssociatedView(), shadowViewTable[viewId].get() }; if (viewTable.find(viewId) != viewTable.end()) - return {viewTable[viewId].get(), shadowViewTable[viewId].get()}; + return { viewTable[viewId].get(), shadowViewTable[viewId].get() }; // If we land here, you asked for a view that we don't have. jassertfalse; - return {nullptr, nullptr}; + return { nullptr, nullptr }; } - View* ViewManager::getViewByRefId (const juce::Identifier& refId) + View* ViewManager::getViewByRefId(const juce::Identifier& refId) { if (refId == getRootViewRefId()) return shadowViewTable[rootId]->getAssociatedView(); @@ -263,9 +263,9 @@ namespace blueprint juce::Identifier ViewManager::getRootViewRefId() { - View* root = shadowViewTable[rootId]->getAssociatedView(); - jassert(root); + View* root = shadowViewTable[rootId]->getAssociatedView(); + jassert(root); - return root->getRefId(); + return root->getRefId(); } -} +} // namespace blueprint diff --git a/blueprint/core/blueprint_ViewManager.h b/blueprint/core/blueprint_ViewManager.h index 5aa85600..0009bb94 100644 --- a/blueprint/core/blueprint_ViewManager.h +++ b/blueprint/core/blueprint_ViewManager.h @@ -11,8 +11,8 @@ #include -#include "blueprint_View.h" #include "blueprint_ShadowView.h" +#include "blueprint_View.h" namespace blueprint { @@ -65,7 +65,7 @@ namespace blueprint void insertChild(ViewId parentId, ViewId childId, int index = -1); /** Removes a child View from the given parent View */ - void removeChild (ViewId parentId, ViewId childId); + void removeChild(ViewId parentId, ViewId childId); /** Recursively computes the shadow tree layout on the root ShadowView, then traverses the tree flushing new layout bounds to the associated view components. @@ -78,26 +78,26 @@ namespace blueprint /** Invokes an exported native method on the given View instance. * This method is used to allow JS code to invoke a native function on a ViewInstance using React refs. **/ - juce::var invokeViewMethod(ViewId viewId, const juce::String &method, const juce::var::NativeFunctionArgs &args); + juce::var invokeViewMethod(ViewId viewId, const juce::String& method, const juce::var::NativeFunctionArgs& args); //============================================================================== private: - void enumerateChildViewIds (std::vector& ids, View* v); + void enumerateChildViewIds(std::vector& ids, View* v); /** Returns a pointer pair to the view associated to the given id. */ - std::pair getViewHandle (ViewId viewId); + std::pair getViewHandle(ViewId viewId); /** Walks the view table, returning the first view with a `refId` * whose value equals the provided id. */ - View* getViewByRefId (const juce::Identifier& refId); + View* getViewByRefId(const juce::Identifier& refId); /** Helper function to return refId of the root view */ juce::Identifier getRootViewRefId(); - ViewId rootId; - std::map> viewTable; + ViewId rootId; + std::map> viewTable; std::map> shadowViewTable; - std::map viewFactories; + std::map viewFactories; }; -} +} // namespace blueprint