diff --git a/Submodules/UIKit/CMakeLists.txt b/Submodules/UIKit/CMakeLists.txt index 2ab2d6c..a6df6db 100644 --- a/Submodules/UIKit/CMakeLists.txt +++ b/Submodules/UIKit/CMakeLists.txt @@ -39,6 +39,8 @@ add_library(UIKit lib/UIResponder.cpp lib/UITapGestureRecognizer.cpp lib/UITouch.cpp + lib/UITraitCollection.cpp + lib/UITraitEnvironment.cpp lib/UIView.cpp lib/UIViewAnimationGroup.cpp lib/UIViewAnimationOptions.cpp diff --git a/Submodules/UIKit/include/CABlurLayer.h b/Submodules/UIKit/include/CABlurLayer.h index f22818d..bafdfbd 100644 --- a/Submodules/UIKit/include/CABlurLayer.h +++ b/Submodules/UIKit/include/CABlurLayer.h @@ -21,7 +21,7 @@ class CABlurLayer: public CALayer { void update(std::shared_ptr presentation, std::shared_ptr animation, float progress) override; private: - NXFloat _blurValue = 20; + NXFloat _blurValue = 10; }; } diff --git a/Submodules/UIKit/include/SkiaCtx.h b/Submodules/UIKit/include/SkiaCtx.h index f165268..d18ed25 100644 --- a/Submodules/UIKit/include/SkiaCtx.h +++ b/Submodules/UIKit/include/SkiaCtx.h @@ -5,6 +5,7 @@ #include "include/core/SkSurface.h" #include #include "include/core/SkFontMgr.h" +#include #include namespace NXKit { @@ -23,6 +24,8 @@ class SkiaCtx { virtual float getScaleFactor() { return 1; } virtual sk_sp getFontMgr() { return fontMgr; } + virtual UIUserInterfaceStyle getThemeMode() { return UIUserInterfaceStyle::light; } + static std::shared_ptr main() { return _main; } static std::shared_ptr _main; protected: diff --git a/Submodules/UIKit/include/UIColor.h b/Submodules/UIKit/include/UIColor.h index 4489573..4a1c075 100644 --- a/Submodules/UIKit/include/UIColor.h +++ b/Submodules/UIKit/include/UIColor.h @@ -1,13 +1,18 @@ #pragma once +#include #include #include +#include +#include namespace NXKit { class UIColor { public: UIColor(); + UIColor(std::function)> dynamicProvider); + UIColor(int rawValue); UIColor(unsigned char red, unsigned char green, unsigned char blue); UIColor(unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha); @@ -19,27 +24,60 @@ class UIColor { bool operator==(const UIColor& rhs) const; UIColor interpolationTo(UIColor endResult, NXFloat progress); - uint32_t raw() const { return color; } + uint32_t raw() const; + // Transparent static UIColor clear; + + // Fixed + static UIColor black; + static UIColor darkGray; + static UIColor gray; + static UIColor lightGray; + static UIColor white; static UIColor red; - static UIColor green; - static UIColor blue; static UIColor orange; + static UIColor yellow; + static UIColor green; static UIColor cyan; - static UIColor white; - static UIColor black; - static UIColor gray; + static UIColor blue; + static UIColor purple; + static UIColor magenta; + static UIColor brown; + + // Adaptable + static UIColor systemRed; + static UIColor systemOrange; + static UIColor systemYellow; + static UIColor systemGreen; + static UIColor systemMint; + static UIColor systemTeal; + static UIColor systemCyan; + static UIColor systemBlue; + static UIColor systemIndigo; + static UIColor systemPurple; + static UIColor systemPink; + static UIColor systemBrown; + // Label + static UIColor label; + static UIColor secondaryLabel; + static UIColor tertiaryLabel; + static UIColor quaternaryLabel; + + // Separator static UIColor separator; + + // Standard content background static UIColor systemBackground; static UIColor secondarySystemBackground; static UIColor tetriarySystemBackground; + static UIColor tint; private: - friend class CALayer; - uint32_t color; + std::optional)>> dynamicProvider; + uint32_t color = 0xFF600060; }; } diff --git a/Submodules/UIKit/include/UITraitCollection.h b/Submodules/UIKit/include/UITraitCollection.h new file mode 100644 index 0000000..62fa8a1 --- /dev/null +++ b/Submodules/UIKit/include/UITraitCollection.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include + +namespace NXKit { + +enum class UIUserInterfaceStyle { + unspecified, + light, + dark +}; + +class UITraitCollection { +public: + std::shared_ptr copy(); + + UIUserInterfaceStyle userInterfaceStyle() const { return _userInterfaceStyle; } + NXFloat displayScale() const { return _displayScale; } + + static std::shared_ptr current() { return _current; } + static void setCurrent(std::shared_ptr current) { _current = current; } + +private: + friend bool applicationRunLoop(); + + static std::shared_ptr _current; + + UIUserInterfaceStyle _userInterfaceStyle = UIUserInterfaceStyle::unspecified; + NXFloat _displayScale = 1; +}; + +} diff --git a/Submodules/UIKit/include/UITraitEnvironment.h b/Submodules/UIKit/include/UITraitEnvironment.h new file mode 100644 index 0000000..f4519ce --- /dev/null +++ b/Submodules/UIKit/include/UITraitEnvironment.h @@ -0,0 +1,24 @@ +#pragma once + +#include + +namespace NXKit { + +class UITraitEnvironment { +public: + std::shared_ptr traitCollection() const { return _traitCollection; } + + virtual void traitCollectionDidChange(std::shared_ptr previousTraitCollection); + +protected: + friend bool applicationRunLoop(); + friend class UIWindow; + friend class UIViewController; + friend class UIView; + + std::shared_ptr _traitCollection; + + virtual void invalidateTraitCollection() {} +}; + +} diff --git a/Submodules/UIKit/include/UIView.h b/Submodules/UIKit/include/UIView.h index 1553925..ce8d2f1 100644 --- a/Submodules/UIKit/include/UIView.h +++ b/Submodules/UIKit/include/UIView.h @@ -1,6 +1,7 @@ #pragma once #include "CALayer.h" +#include #include #include #include @@ -11,7 +12,7 @@ namespace NXKit { class UIWindow; class UIViewController; class UIGestureRecognizer; -class UIView: public UIResponder, public CALayerDelegate, public enable_shared_from_this { +class UIView: public UIResponder, public UITraitEnvironment, public CALayerDelegate, public enable_shared_from_this { public: UIView(NXRect frame = NXRect(), std::shared_ptr layer = new_shared()); @@ -65,6 +66,8 @@ class UIView: public UIResponder, public CALayerDelegate, public enable_shared_f std::shared_ptr layer() const { return _layer; }; + void traitCollectionDidChange(std::shared_ptr previousTraitCollection) override; + // Layout void setNeedsDisplay() { _needsDisplay = true; } void setNeedsLayout();// { setNeedsDisplay(); _needsLayout = true; } diff --git a/Submodules/UIKit/include/UIViewController.h b/Submodules/UIKit/include/UIViewController.h index 70e534e..c87a936 100644 --- a/Submodules/UIKit/include/UIViewController.h +++ b/Submodules/UIKit/include/UIViewController.h @@ -4,7 +4,7 @@ namespace NXKit { -class UIViewController: public UIResponder, public enable_shared_from_this { +class UIViewController: public UIResponder, public UITraitEnvironment, public enable_shared_from_this { public: std::map> idStorage; @@ -45,6 +45,9 @@ class UIViewController: public UIResponder, public enable_shared_from_this otherViewController, bool animated, std::function completion = [](){}); void dismiss(bool animated, std::function completion = [](){}); + + void traitCollectionDidChange(std::shared_ptr previousTraitCollection) override; + // Focus // virtual std::shared_ptr parentFocusEnvironment() override; diff --git a/Submodules/UIKit/include/UIWindow.h b/Submodules/UIKit/include/UIWindow.h index c224f6b..bc0fc29 100644 --- a/Submodules/UIKit/include/UIWindow.h +++ b/Submodules/UIKit/include/UIWindow.h @@ -27,6 +27,7 @@ class UIWindow: public UIView { virtual void pressesEnded(std::set> pressees, std::shared_ptr event) override; virtual void pressesCancelled(std::set> pressees, std::shared_ptr event) override; + void traitCollectionDidChange(std::shared_ptr previousTraitCollection) override; private: std::shared_ptr _rootViewController; std::vector> _presentedViewControllers; diff --git a/Submodules/UIKit/include/platforms/ios/SkiaCtx_ios.h b/Submodules/UIKit/include/platforms/ios/SkiaCtx_ios.h index 2f605ef..5342614 100644 --- a/Submodules/UIKit/include/platforms/ios/SkiaCtx_ios.h +++ b/Submodules/UIKit/include/platforms/ios/SkiaCtx_ios.h @@ -19,6 +19,8 @@ class SkiaCtx_ios : public SkiaCtx_sdlBase { sk_sp directContext() override { return context; } + NXKit::UIUserInterfaceStyle getThemeMode() override; + private: sk_sp context; sk_sp surface; diff --git a/Submodules/UIKit/include/tools/Tools.hpp b/Submodules/UIKit/include/tools/Tools.hpp index 0858ea1..f5e3a46 100644 --- a/Submodules/UIKit/include/tools/Tools.hpp +++ b/Submodules/UIKit/include/tools/Tools.hpp @@ -11,6 +11,7 @@ #include #include "OptionSet.hpp" +#include "SharedBase.hpp" namespace NXKit { @@ -26,4 +27,4 @@ std::optional any_optional_cast(std::optional obj) { } } -} \ No newline at end of file +} diff --git a/Submodules/UIKit/lib/CABlurLayer.cpp b/Submodules/UIKit/lib/CABlurLayer.cpp index 4a06cfb..154595d 100644 --- a/Submodules/UIKit/lib/CABlurLayer.cpp +++ b/Submodules/UIKit/lib/CABlurLayer.cpp @@ -1,6 +1,7 @@ #include #include +#include "include/core/SkRRect.h" #include "include/effects/SkImageFilters.h" using namespace NXKit; @@ -29,11 +30,17 @@ void CABlurLayer::draw(SkCanvas* context) { context->save(); SkRect rect = SkRect::MakeXYWH(0, 0, bounds().width(), bounds().height()); - context->clipRect(rect, true); + float radii = cornerRadius(); + SkVector corners[] = {{radii, radii}, {radii, radii}, {radii, radii}, {radii, radii}}; + SkRRect rrect; + rrect.setRectRadii(rect, corners); + context->clipRRect(rrect, true); // // Make a separate layer using the blur filter, clipped to the middle rectangle's bounds SkCanvas::SaveLayerRec slr(&rect, &blurPaint, SkCanvas::kInitWithPrevious_SaveLayerFlag); context->saveLayer(slr); context->restore(); + + context->drawColor(0x40FFFFFF); context->restore(); } diff --git a/Submodules/UIKit/lib/CALayer.cpp b/Submodules/UIKit/lib/CALayer.cpp index c105a38..74003ac 100644 --- a/Submodules/UIKit/lib/CALayer.cpp +++ b/Submodules/UIKit/lib/CALayer.cpp @@ -6,8 +6,8 @@ #include #include #include -#include "include/core/SkRRect.h" +#include "include/core/SkRRect.h" #include "include/effects/SkGradientShader.h" #include "include/effects/SkImageFilters.h" @@ -203,7 +203,7 @@ void CALayer::skiaRender(SkCanvas* canvas) { // Background color if (_backgroundColor.has_value()) { - paint.setColor(_backgroundColor->color); + paint.setColor(_backgroundColor->raw()); SkRect rect = SkRect::MakeXYWH(0, 0, _bounds.width(), _bounds.height()); SkRRect rrect; diff --git a/Submodules/UIKit/lib/UIApplicationMain.cpp b/Submodules/UIKit/lib/UIApplicationMain.cpp index 9c6c322..0f1998e 100644 --- a/Submodules/UIKit/lib/UIApplicationMain.cpp +++ b/Submodules/UIKit/lib/UIApplicationMain.cpp @@ -18,6 +18,19 @@ bool applicationRunLoop() { // Move to UIRenderer auto keyWindow = UIApplication::shared->keyWindow.lock(); + auto scale = SkiaCtx::_main->getScaleFactor(); + + if (keyWindow->_traitCollection == nullptr + || keyWindow->_traitCollection->_userInterfaceStyle != SkiaCtx::main()->getThemeMode() + || keyWindow->_traitCollection->_displayScale != scale) + { + auto oldCollection = keyWindow->_traitCollection; + keyWindow->_traitCollection = new_shared(); + keyWindow->_traitCollection->_displayScale = scale; + keyWindow->_traitCollection->_userInterfaceStyle = SkiaCtx::main()->getThemeMode(); + keyWindow->traitCollectionDidChange(oldCollection); + } + UIView::animateIfNeeded(currentTime); keyWindow->drawAndLayoutTreeIfNeeded(); @@ -28,7 +41,6 @@ bool applicationRunLoop() { canvas->clear(SK_ColorTRANSPARENT); canvas->save(); - auto scale = SkiaCtx::_main->getScaleFactor(); canvas->scale(scale, scale); UIView::animate(0.3, [keyWindow]() { diff --git a/Submodules/UIKit/lib/UIColor.cpp b/Submodules/UIKit/lib/UIColor.cpp index 6cf6297..e473265 100644 --- a/Submodules/UIKit/lib/UIColor.cpp +++ b/Submodules/UIKit/lib/UIColor.cpp @@ -4,21 +4,62 @@ using namespace NXKit; +#define UIColorThemed(lightColor, darkColor) \ +UIColor([](auto collection) {\ +if (collection->userInterfaceStyle() == UIUserInterfaceStyle::dark) \ + return darkColor; \ +else \ + return lightColor;\ +}) + +// Transparent UIColor UIColor::clear = UIColor(0, 0, 0, 0); + +// Fixed +UIColor UIColor::black = UIColor(0, 0, 0); +UIColor UIColor::darkGray = UIColor(85, 85, 85); +UIColor UIColor::gray = UIColor(128, 128, 128); +UIColor UIColor::lightGray = UIColor(170, 170, 170); +UIColor UIColor::white = UIColor(255, 255, 255); UIColor UIColor::red = UIColor(255, 0, 0); +UIColor UIColor::orange = UIColor(255, 128, 0); +UIColor UIColor::yellow = UIColor(255, 255, 0); UIColor UIColor::green = UIColor(0, 255, 0); +UIColor UIColor::cyan = UIColor(0, 255, 255); UIColor UIColor::blue = UIColor(0, 0, 255); -UIColor UIColor::orange = UIColor(255, 150, 0); -UIColor UIColor::cyan = UIColor(0, 150, 255); -UIColor UIColor::white = UIColor(255, 255, 255); -UIColor UIColor::black = UIColor(0, 0, 0); -UIColor UIColor::gray = UIColor(155, 155, 155); - -UIColor UIColor::separator = UIColor(208, 208, 208); -UIColor UIColor::systemBackground = UIColor(235, 235, 235); -UIColor UIColor::secondarySystemBackground = UIColor(240, 240, 240); -UIColor UIColor::tetriarySystemBackground = UIColor(252, 255, 248); -UIColor UIColor::tint = UIColor(49, 79, 235); +UIColor UIColor::purple = UIColor(128, 0, 128); +UIColor UIColor::magenta = UIColor(255, 0, 255); +UIColor UIColor::brown = UIColor(153, 102, 51); + +// Adaptable +UIColor UIColor::systemRed = UIColorThemed(UIColor(255, 59, 48), UIColor(255, 69, 58)); +UIColor UIColor::systemOrange = UIColorThemed(UIColor(255, 149, 0), UIColor(255, 159, 10)); +UIColor UIColor::systemYellow = UIColorThemed(UIColor(242, 204, 0), UIColor(255, 214, 10)); +UIColor UIColor::systemGreen = UIColorThemed(UIColor(52, 199, 89), UIColor(48, 209, 88)); +UIColor UIColor::systemMint = UIColorThemed(UIColor(0, 199, 190), UIColor(99, 230, 226)); +UIColor UIColor::systemTeal = UIColorThemed(UIColor(48, 176, 199), UIColor(64, 200, 224)); +UIColor UIColor::systemCyan = UIColorThemed(UIColor(50, 173, 230), UIColor(100, 210, 255)); +UIColor UIColor::systemBlue = UIColorThemed(UIColor(0, 122, 255), UIColor(10, 132, 255)); +UIColor UIColor::systemIndigo = UIColorThemed(UIColor(88, 86, 214), UIColor(94, 92, 230)); +UIColor UIColor::systemPurple = UIColorThemed(UIColor(175, 82, 222), UIColor(191, 90, 242)); +UIColor UIColor::systemPink = UIColorThemed(UIColor(255, 45, 85), UIColor(255, 55, 95)); +UIColor UIColor::systemBrown = UIColorThemed(UIColor(162, 132, 94), UIColor(172, 142, 104)); + +// Label +UIColor UIColor::label = UIColorThemed(UIColor(0, 0, 0), UIColor(255, 255, 255)); +UIColor UIColor::secondaryLabel = UIColorThemed(UIColor(0x993c3c43), UIColor(0x99ebebf5)); +UIColor UIColor::tertiaryLabel = UIColorThemed(UIColor(0x4c3c3c43), UIColor(0x4cebebf5)); +UIColor UIColor::quaternaryLabel = UIColorThemed(UIColor(0x2d3c3c43), UIColor(0x28ebebf5)); + +// Standard content background +UIColor UIColor::systemBackground = UIColorThemed(UIColor(255, 255, 255), UIColor(0, 0, 0)); +UIColor UIColor::secondarySystemBackground = UIColorThemed(UIColor(242, 242, 242), UIColor(28, 28, 30)); +UIColor UIColor::tetriarySystemBackground = UIColorThemed(UIColor(255, 255, 255), UIColor(44, 44, 46)); + +// Separator +UIColor UIColor::separator = UIColorThemed(UIColor(0x4a3c3c43), UIColor(0x99545458)); + +UIColor UIColor::tint = systemBlue; UIColor::UIColor(unsigned char r, unsigned char g, unsigned char b, unsigned char a) { color = (a & 0xff) << 24 | (r & 0xff) << 16 | (g & 0xff) << 8 | (b & 0xff); @@ -26,25 +67,39 @@ UIColor::UIColor(unsigned char r, unsigned char g, unsigned char b, unsigned cha UIColor::UIColor(unsigned char r, unsigned char g, unsigned char b): UIColor(r, g, b, 255) {} UIColor::UIColor(): UIColor(0, 0, 0) {} +UIColor::UIColor(int rawValue): color(rawValue) {} + + +UIColor::UIColor(std::function)> dynamicProvider) { + this->dynamicProvider = dynamicProvider; +} + +uint32_t UIColor::raw() const { + if (dynamicProvider == std::nullopt) { + return color; + } + + return dynamicProvider.value()(UITraitCollection::current()).raw(); +} unsigned char UIColor::r() { - return static_cast((color >> 16) & 0xff); + return static_cast((raw() >> 16) & 0xff); } unsigned char UIColor::g() { - return static_cast((color >> 8) & 0xff); + return static_cast((raw() >> 8) & 0xff); } unsigned char UIColor::b() { - return static_cast(color & 0xff); + return static_cast(raw() & 0xff); } unsigned char UIColor::a() { - return static_cast((color >> 24) & 0xff); + return static_cast((raw() >> 24) & 0xff); } bool UIColor::operator==(const UIColor& rhs) const { - return this->color == rhs.color; + return this->raw() == rhs.raw(); } UIColor UIColor::interpolationTo(UIColor endResult, NXFloat progress) { diff --git a/Submodules/UIKit/lib/UITraitCollection.cpp b/Submodules/UIKit/lib/UITraitCollection.cpp new file mode 100644 index 0000000..53a4e61 --- /dev/null +++ b/Submodules/UIKit/lib/UITraitCollection.cpp @@ -0,0 +1,13 @@ +#include +#include + +using namespace NXKit; + +std::shared_ptr UITraitCollection::_current = new_shared(); + +std::shared_ptr UITraitCollection::copy() { + auto newCollection = new_shared(); + newCollection->_userInterfaceStyle = _userInterfaceStyle; + newCollection->_displayScale = _displayScale; + return newCollection; +} diff --git a/Submodules/UIKit/lib/UITraitEnvironment.cpp b/Submodules/UIKit/lib/UITraitEnvironment.cpp new file mode 100644 index 0000000..4bf4007 --- /dev/null +++ b/Submodules/UIKit/lib/UITraitEnvironment.cpp @@ -0,0 +1,7 @@ +#include + +using namespace NXKit; + +void UITraitEnvironment::traitCollectionDidChange(std::shared_ptr previousTraitCollection) { + invalidateTraitCollection(); +} diff --git a/Submodules/UIKit/lib/UIView.cpp b/Submodules/UIKit/lib/UIView.cpp index 858d95c..c8da8bd 100644 --- a/Submodules/UIKit/lib/UIView.cpp +++ b/Submodules/UIKit/lib/UIView.cpp @@ -43,6 +43,11 @@ void UIView::setCenter(NXPoint position) { setFrame(frame); } +NXPoint UIView::center() const { + auto frame = this->frame(); + return { frame.midX(), frame.midY() }; +} + void UIView::addGestureRecognizer(std::shared_ptr gestureRecognizer) { gestureRecognizer->_view = weak_from_this(); _gestureRecognizers.push_back(gestureRecognizer); @@ -128,22 +133,30 @@ void UIView::drawAndLayoutTreeIfNeeded() { if (visibleLayer->isHidden() || visibleLayer->opacity() < 0.01f) { return; } + UITraitCollection::setCurrent(traitCollection()); + if (_contentMode == UIViewContentMode::redraw) { if (visibleLayer->contents() && visibleLayer->contents()->size() != visibleLayer->bounds().size) { setNeedsDisplay(); } } + UITraitCollection::setCurrent(traitCollection()); + if (visibleLayer->_needsDisplay) { visibleLayer->display(); visibleLayer->_needsDisplay = false; } + UITraitCollection::setCurrent(traitCollection()); + if (_needsDisplay) { draw(); _needsDisplay = false; } + UITraitCollection::setCurrent(traitCollection()); + // updateSafeAreaInsetsIfNeeded(); // updateLayoutMarginIfNeeded(); layoutIfNeeded(); @@ -244,7 +257,7 @@ NXPoint UIView::convertToView(NXPoint point, std::shared_ptr toView) { } std::shared_ptr UIView::hitTest(NXPoint point, UIEvent* withEvent) { - if (isHidden() || !_isUserInteractionEnabled || alpha() == 0 || !anyCurrentlyRunningAnimationsAllowUserInteraction()) + if (isHidden() || !_isUserInteractionEnabled || alpha() < 0.01 || !anyCurrentlyRunningAnimationsAllowUserInteraction()) return nullptr; if (!this->point(point, withEvent)) @@ -257,9 +270,6 @@ std::shared_ptr UIView::hitTest(NXPoint point, UIEvent* withEvent) { if (test) return test; } - if (backgroundColor() == std::nullopt || backgroundColor() == UIColor::clear) - return nullptr; - return shared_from_this(); } @@ -351,6 +361,17 @@ std::shared_ptr UIView::actionForKey(std::string event) { void UIView::display(std::shared_ptr layer) { } +void UIView::traitCollectionDidChange(std::shared_ptr previousTraitCollection) { + UITraitEnvironment::traitCollectionDidChange(previousTraitCollection); + for (auto subview : _subviews) { + // If subview has controller, it's controller will update related traitCollection + if (!subview->_parentController.expired()) continue; + + subview->_traitCollection = _traitCollection; + subview->traitCollectionDidChange(previousTraitCollection); + } +} + // MARK: - Layout void UIView::setNeedsLayout() { setNeedsDisplay(); diff --git a/Submodules/UIKit/lib/UIViewController.cpp b/Submodules/UIKit/lib/UIViewController.cpp index aa8f54b..eff5d63 100644 --- a/Submodules/UIKit/lib/UIViewController.cpp +++ b/Submodules/UIKit/lib/UIViewController.cpp @@ -155,6 +155,18 @@ void UIViewController::dismiss(bool animated, std::function completion) }); } +void UIViewController::traitCollectionDidChange(std::shared_ptr previousTraitCollection) { + UITraitEnvironment::traitCollectionDidChange(previousTraitCollection); + if (_view) { + _view->_traitCollection = _traitCollection; + _view->traitCollectionDidChange(previousTraitCollection); + } + for (auto child : _children) { + child->_traitCollection = _traitCollection; + child->UITraitEnvironment::traitCollectionDidChange(previousTraitCollection); + } +} + //std::shared_ptr UIViewController::parentFocusEnvironment() { // return std::dynamic_pointer_cast(next()); //} diff --git a/Submodules/UIKit/lib/UIWindow.cpp b/Submodules/UIKit/lib/UIWindow.cpp index 695e07b..821d005 100644 --- a/Submodules/UIKit/lib/UIWindow.cpp +++ b/Submodules/UIKit/lib/UIWindow.cpp @@ -179,3 +179,11 @@ void UIWindow::pressesCancelled(std::set> pressees, std UIView::pressesCancelled(pressees, event); // focusSystem()->sendEvent(event); } + +void UIWindow::traitCollectionDidChange(std::shared_ptr previousTraitCollection) { + UITraitEnvironment::traitCollectionDidChange(previousTraitCollection); + if (!rootViewController()) return; + + rootViewController()->_traitCollection = _traitCollection; + rootViewController()->traitCollectionDidChange(previousTraitCollection); +} diff --git a/Submodules/UIKit/lib/platforms/apple/ios/SkiaCtx_ios.mm b/Submodules/UIKit/lib/platforms/apple/ios/SkiaCtx_ios.mm index 0afd2f5..61019d5 100644 --- a/Submodules/UIKit/lib/platforms/apple/ios/SkiaCtx_ios.mm +++ b/Submodules/UIKit/lib/platforms/apple/ios/SkiaCtx_ios.mm @@ -51,6 +51,15 @@ return UIApplication.sharedApplication.keyWindow.traitCollection.displayScale; } +NXKit::UIUserInterfaceStyle SkiaCtx_ios::getThemeMode() { + auto window = UIApplication.sharedApplication.keyWindow; + if (window.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) { + return NXKit::UIUserInterfaceStyle::dark; + } else { + return NXKit::UIUserInterfaceStyle::light; + } +} + sk_sp SkiaCtx_ios::getBackbufferSurface() { auto size = getSize(); if (_size.width == size.width && _size.height == size.height && surface != nullptr) { return surface; } diff --git a/app/Screens/TestViewController/TestViewController.cpp b/app/Screens/TestViewController/TestViewController.cpp index 32bb714..8e58d44 100644 --- a/app/Screens/TestViewController/TestViewController.cpp +++ b/app/Screens/TestViewController/TestViewController.cpp @@ -6,12 +6,12 @@ using namespace NXKit; void animateCube(std::shared_ptr view) { UIView::animate(2.5, 0, 0.5, 2, UIViewAnimationOptions::none, [view]() { view->setTransform(NXAffineTransform::identity.rotationBy(55)); - view->setBackgroundColor(UIColor::orange); + view->setBackgroundColor(UIColor::systemOrange); }, [view](bool res) { DispatchQueue::main()->asyncAfter(1, [view]() { UIView::animate(2.5, [view]() { view->setTransform(NXAffineTransform::identity.rotationBy(10)); - view->setBackgroundColor(UIColor::blue); + view->setBackgroundColor(UIColor::systemBlue); }, [view](bool res) { DispatchQueue::main()->asyncAfter(1, [view]() { animateCube(view); @@ -36,14 +36,14 @@ void animateBlur(std::shared_ptr view) { void animateLabel(std::shared_ptr label) { UIView::animate(5, [label]() { label->setFrame({ 200, 100, 140, 88 }); - label->setTextColor(UIColor::cyan); - label->setBackgroundColor(UIColor::green); + label->setTextColor(UIColor::systemCyan); + label->setBackgroundColor(UIColor::systemGreen); label->setFontWeight(100); }, [label](bool res) { UIView::animate(5, [label]() { label->setFrame({ 200, 100, 240, 88 }); label->setTextColor(UIColor::black); - label->setBackgroundColor(UIColor::red); + label->setBackgroundColor(UIColor::systemRed); label->setFontWeight(1000); }, [label](bool res) { animateLabel(label); @@ -98,7 +98,7 @@ void TestViewController::loadView() { auto imageView = new_shared(); imageView->setImage(image); imageView->setFrame({ 0, 0, 120, 120 }); - imageView->setBackgroundColor(UIColor::green); + imageView->setBackgroundColor(UIColor::systemGreen); imageView->setContentMode(UIViewContentMode::topLeft); subview->addSubview(imageView); @@ -108,14 +108,11 @@ void TestViewController::loadView() { label->setFrame({ 200, 100, 240, 88 }); label->setText("Привет\nебать,\nэто\nкириллица,\nнахуй!!!!"); label->setTextAlignment(NSTextAlignment::center); - label->setBackgroundColor(UIColor::red); + label->setBackgroundColor(UIColor::systemRed); label->setContentMode(NXKit::UIViewContentMode::center); rootView->addSubview(label); - auto blur = new_shared(); - blur->setFrame({ 80, 80, 240, 240 }); - rootView->addSubview(blur); - animateBlur(blur); +// animateBlur(blur); bottomBar = new_shared(); bottomBar->setBackgroundColor(UIColor::gray); @@ -123,7 +120,7 @@ void TestViewController::loadView() { label2 = new_shared(); label2->setText("Test text\nTry to fit me!!!"); - label2->setBackgroundColor(UIColor::cyan); + label2->setBackgroundColor(UIColor::systemCyan); label2->setFrame({ 100, 200, 0, 0 }); rootView->addSubview(label2); @@ -148,37 +145,44 @@ void TestViewController::loadView() { }; button->addGestureRecognizer(tapGesture); - auto dragMeView = new_shared(); - dragMeView->setText("Drag me!"); - dragMeView->setFontWeight(600); - dragMeView->setTextAlignment(NSTextAlignment::center); - dragMeView->setFrame({ 100, 400, 200, 200 }); - dragMeView->layer()->setCornerRadius(12); - dragMeView->setBackgroundColor(UIColor::orange); - rootView->addSubview(dragMeView); + dragMeViewLabel = new_shared(); + dragMeViewLabel->setText("Drag me!"); + dragMeViewLabel->setFontWeight(600); + dragMeViewLabel->setTextAlignment(NSTextAlignment::center); +// dragMeViewLabel->setFrame({ 80, 110, 44, 100 }); + + auto blur = new_shared(); + blur->setFrame({ 80, 200, 240, 240 }); + rootView->addSubview(blur); + blur->layer()->setCornerRadius(12); + + blur->addSubview(dragMeViewLabel); auto panGesture = new_shared(); - panGesture->onStateChanged = [this, dragMeView, panGesture](UIGestureRecognizerState status) { + panGesture->onStateChanged = [this, panGesture](UIGestureRecognizerState status) { static NXPoint initial; + auto _view = panGesture->view().lock(); + if (!_view) return; + switch (status) { case UIGestureRecognizerState::began: { - initial = dragMeView->frame().origin; + initial = _view->frame().origin; break; } case UIGestureRecognizerState::changed: { auto translation = panGesture->translationInView(view()); - auto frame = dragMeView->frame(); + auto frame = _view->frame(); frame.origin.x = initial.x + translation.x; frame.origin.y = initial.y + translation.y; - dragMeView->setFrame(frame); + _view->setFrame(frame); break; } default: break; } }; - dragMeView->addGestureRecognizer(panGesture); + blur->addGestureRecognizer(panGesture); setView(rootView); } @@ -194,6 +198,10 @@ void TestViewController::viewDidLoad() { void TestViewController::viewDidLayoutSubviews() { UIViewController::viewDidLayoutSubviews(); + auto bounds = dragMeViewLabel->superview().lock()->bounds(); + dragMeViewLabel->sizeToFit(); + dragMeViewLabel->setCenter({ bounds.midX(), bounds.midY() }); + label2->sizeToFit(); auto frame = view()->frame(); diff --git a/app/Screens/TestViewController/TestViewController.hpp b/app/Screens/TestViewController/TestViewController.hpp index 4c335be..206a4ce 100644 --- a/app/Screens/TestViewController/TestViewController.hpp +++ b/app/Screens/TestViewController/TestViewController.hpp @@ -10,6 +10,7 @@ class TestViewController: public NXKit::UIViewController { void viewDidLayoutSubviews() override; private: + std::shared_ptr dragMeViewLabel; std::shared_ptr label; std::shared_ptr label2; std::shared_ptr bottomBar;