From 836628acbd1dbd35be529b748d06c73493171006 Mon Sep 17 00:00:00 2001 From: Alexandr Nevyantsev Date: Wed, 20 Oct 2021 20:37:20 +0300 Subject: [PATCH 01/13] Add test implementation of spm --- ExampleSPM/.swiftlint.yml | 28 + .../project.pbxproj | 656 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../LightweightCharts-Example.xcscheme | 111 +++ .../LightweightCharts/AppDelegate.swift | 19 + .../Base.lproj/LaunchScreen.xib | 34 + .../AddAndRemovePriceLineViewController.swift | 110 +++ .../Example/BarChartViewController.swift | 208 ++++++ .../CandlestickChartViewController.swift | 218 ++++++ .../CustomFontFamilyViewController.swift | 235 +++++++ .../Example/CustomLocaleViewController.swift | 230 ++++++ .../CustomPriceFormatterViewController.swift | 328 +++++++++ .../Example/CustomThemesViewController.swift | 301 ++++++++ .../CustomWatermarkViewController.swift | 223 ++++++ .../Example/FitContentViewController.swift | 413 +++++++++++ .../FloatingTooltipViewController.swift | 435 ++++++++++++ .../GoToRealtimeButtonViewController.swift | 265 +++++++ .../Example/IntradayDataViewController.swift | 209 ++++++ .../InvertedPriceScaleViewController.swift | 210 ++++++ .../Example/LegendViewController.swift | 268 +++++++ .../LogarithmicPriceScaleViewController.swift | 211 ++++++ .../MagnifierTooltipViewController.swift | 448 ++++++++++++ .../Example/MarkersViewController.swift | 85 +++ .../Example/NoPriceScaleViewController.swift | 215 ++++++ .../Example/NoTimeScaleViewController.swift | 462 ++++++++++++ .../PercentagePriceScaleViewController.swift | 379 ++++++++++ .../Example/PriceLineViewController.swift | 83 +++ .../PriceScaleAtLeftViewController.swift | 211 ++++++ .../Example/RangeSwitcherViewController.swift | 598 ++++++++++++++++ .../RealtimeEmulationViewController.swift | 305 ++++++++ .../Example/TableViewController.swift | 81 +++ .../ThreeLineLegendViewController.swift | 448 ++++++++++++ .../TrackingTooltipViewController.swift | 270 +++++++ .../Example/VolumeStudyViewController.swift | 382 ++++++++++ .../AppIcon.appiconset/Contents.json | 53 ++ ExampleSPM/LightweightCharts/Info.plist | 37 + .../LightweightCharts/Views/TooltipView.swift | 70 ++ ExampleSPM/Tests/Info.plist | 24 + ExampleSPM/Tests/Tests.swift | 16 + .../project.pbxproj | 469 +++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../LightwehgitCharts.md | 13 + .../LightwehgitCharts/LightwehgitCharts.h | 18 + .../LightwehgitChartsTests.swift | 33 + LightweightCharts/.gitignore | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + LightweightCharts/Assets/.gitkeep | 0 LightweightCharts/Assets/content-setup.js | 5 - LightweightCharts/Assets/wrapper_functions.js | 56 -- LightweightCharts/Classes/.gitkeep | 0 .../Extensions/Encodable+JSONString.swift | 15 - .../Extensions/Int+ColorComponent.swift | 10 - .../NSRegularExpression+Color.swift | 30 - .../Extensions/String+UniqueString.swift | 9 - .../Extensions/UIColor+ColorComponents.swift | 11 - .../Classes/Implementations/API/Chart.swift | 223 ------ .../API/LightweightCharts.swift | 209 ------ .../Implementations/API/PriceFormatter.swift | 25 - .../Implementations/API/PriceLine.swift | 27 - .../Implementations/API/PriceScale.swift | 35 - .../API/Series/AreaSeries.swift | 8 - .../API/Series/BarSeries.swift | 8 - .../API/Series/CandlestickSeries.swift | 8 - .../API/Series/HistogramSeries.swift | 8 - .../API/Series/LineSeries.swift | 8 - .../API/Series/SeriesApi+Extension.swift | 112 --- .../API/Series/SeriesObject.swift | 18 - .../Implementations/API/TimeScale.swift | 188 ----- .../Implementations/JavaScriptEvaluator.swift | 12 - .../JavaScriptMessageProducer.swift | 8 - .../Implementations/JavaScriptObject.swift | 5 - .../Subscription/MessageHandler.swift | 60 -- .../Subscription/Subscription.swift | 22 - .../JavaScriptMethod.swift | 76 -- .../JavaScriptSyncMethod.swift | 7 - .../SyncScriptEvaluating/PromptHandler.swift | 51 -- .../Classes/Implementations/WebView.swift | 77 -- .../AutoscaleInfoProvider.swift | 66 -- .../AxisPressedMouseMoveOptions.swift | 13 - .../LightweightChartsModels/BarPrice.swift | 3 - .../LightweightChartsModels/BarsInfo.swift | 17 - .../LightweightChartsModels/BusinessDay.swift | 15 - .../LightweightChartsModels/ChartColor.swift | 203 ------ .../LightweightChartsModels/ColorType.swift | 6 - .../LightweightChartsModels/Coordinate.swift | 3 - .../Data/SeriesData/BarData.swift | 31 - .../Data/SeriesData/HistogramData.swift | 28 - .../Data/SeriesData/LineData.swift | 26 - .../Data/SeriesData/SeriesData.swift | 7 - .../Data/SeriesData/SeriesDataType.swift | 46 -- .../Data/SeriesData/WhitespaceData.swift | 14 - .../LightweightChartsModels/FromToRange.swift | 25 - .../MouseEventParams.swift | 116 ---- .../Basics/LastPriceAnimationMode.swift | 21 - .../Options/Basics/LineStyle.swift | 9 - .../Options/Basics/LineType.swift | 6 - .../Options/Basics/LineWidth.swift | 8 - .../Options/Basics/PriceLineOptions.swift | 26 - .../Options/Basics/PriceLineSource.swift | 12 - .../Options/Basics/PriceScaleOptions.swift | 173 ----- .../Options/Basics/TimeScaleOptions.swift | 93 --- .../Options/ChartOptions/ChartOptions.swift | 131 ---- .../ChartOptions/CrosshairLineOptions.swift | 52 -- .../ChartOptions/CrosshairOptions.swift | 43 -- .../ChartOptions/GridLineOptions.swift | 31 - .../Options/ChartOptions/GridOptions.swift | 34 - .../ChartOptions/HandleScaleOptions.swift | 21 - .../ChartOptions/HandleScrollOptions.swift | 58 -- .../ChartOptions/KineticScrollOptions.swift | 22 - .../Options/ChartOptions/LayoutOptions.swift | 42 -- .../ChartOptions/LocalizationOptions.swift | 69 -- .../ChartOptions/WatermarkOptions.swift | 93 --- .../Options/AreaSeriesOptions.swift | 84 --- .../Options/BarSeriesOptions.swift | 66 -- .../Options/CandlestickSeriesOptions.swift | 128 ---- .../Options/HistogramSeriesOptions.swift | 60 -- .../Options/LineSeriesOptions.swift | 81 --- .../SeriesOptions/SeriesOptionsCommon.swift | 102 --- .../LightweightChartsModels/Point.swift | 13 - .../LightweightChartsModels/PriceFormat.swift | 134 ---- .../SeriesMarker/SeriesMarker.swift | 44 -- .../LightweightChartsModels/SeriesType.swift | 10 - .../SurfaceColor.swift | 58 -- .../TickMarkFormatter.swift | 17 - .../LightweightChartsModels/Time.swift | 38 - .../TogglableOptions.swift | 35 - .../Classes/Protocols/ChartApi.swift | 155 ----- .../Classes/Protocols/PriceFormatterApi.swift | 13 - .../Classes/Protocols/PriceLineApi.swift | 8 - .../Classes/Protocols/PriceScaleApi.swift | 24 - .../Classes/Protocols/SeriesApi.swift | 129 ---- .../Classes/Protocols/TimeScaleApi.swift | 146 ---- LightweightCharts/Package.swift | 28 + LightweightCharts/README.md | 3 + .../LightweightCharts/LightweightCharts.swift | 6 + .../LightweightChartsTests.swift | 11 + 138 files changed, 9505 insertions(+), 4239 deletions(-) create mode 100644 ExampleSPM/.swiftlint.yml create mode 100644 ExampleSPM/LightweightCharts.xcodeproj/project.pbxproj create mode 100644 ExampleSPM/LightweightCharts.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 ExampleSPM/LightweightCharts.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 ExampleSPM/LightweightCharts.xcodeproj/xcshareddata/xcschemes/LightweightCharts-Example.xcscheme create mode 100644 ExampleSPM/LightweightCharts/AppDelegate.swift create mode 100644 ExampleSPM/LightweightCharts/Base.lproj/LaunchScreen.xib create mode 100644 ExampleSPM/LightweightCharts/Example/AddAndRemovePriceLineViewController.swift create mode 100644 ExampleSPM/LightweightCharts/Example/BarChartViewController.swift create mode 100644 ExampleSPM/LightweightCharts/Example/CandlestickChartViewController.swift create mode 100644 ExampleSPM/LightweightCharts/Example/CustomFontFamilyViewController.swift create mode 100644 ExampleSPM/LightweightCharts/Example/CustomLocaleViewController.swift create mode 100644 ExampleSPM/LightweightCharts/Example/CustomPriceFormatterViewController.swift create mode 100644 ExampleSPM/LightweightCharts/Example/CustomThemesViewController.swift create mode 100644 ExampleSPM/LightweightCharts/Example/CustomWatermarkViewController.swift create mode 100644 ExampleSPM/LightweightCharts/Example/FitContentViewController.swift create mode 100644 ExampleSPM/LightweightCharts/Example/FloatingTooltipViewController.swift create mode 100644 ExampleSPM/LightweightCharts/Example/GoToRealtimeButtonViewController.swift create mode 100644 ExampleSPM/LightweightCharts/Example/IntradayDataViewController.swift create mode 100644 ExampleSPM/LightweightCharts/Example/InvertedPriceScaleViewController.swift create mode 100644 ExampleSPM/LightweightCharts/Example/LegendViewController.swift create mode 100644 ExampleSPM/LightweightCharts/Example/LogarithmicPriceScaleViewController.swift create mode 100644 ExampleSPM/LightweightCharts/Example/MagnifierTooltipViewController.swift create mode 100644 ExampleSPM/LightweightCharts/Example/MarkersViewController.swift create mode 100644 ExampleSPM/LightweightCharts/Example/NoPriceScaleViewController.swift create mode 100644 ExampleSPM/LightweightCharts/Example/NoTimeScaleViewController.swift create mode 100644 ExampleSPM/LightweightCharts/Example/PercentagePriceScaleViewController.swift create mode 100644 ExampleSPM/LightweightCharts/Example/PriceLineViewController.swift create mode 100644 ExampleSPM/LightweightCharts/Example/PriceScaleAtLeftViewController.swift create mode 100644 ExampleSPM/LightweightCharts/Example/RangeSwitcherViewController.swift create mode 100644 ExampleSPM/LightweightCharts/Example/RealtimeEmulationViewController.swift create mode 100644 ExampleSPM/LightweightCharts/Example/TableViewController.swift create mode 100644 ExampleSPM/LightweightCharts/Example/ThreeLineLegendViewController.swift create mode 100644 ExampleSPM/LightweightCharts/Example/TrackingTooltipViewController.swift create mode 100644 ExampleSPM/LightweightCharts/Example/VolumeStudyViewController.swift create mode 100644 ExampleSPM/LightweightCharts/Images.xcassets/AppIcon.appiconset/Contents.json create mode 100644 ExampleSPM/LightweightCharts/Info.plist create mode 100644 ExampleSPM/LightweightCharts/Views/TooltipView.swift create mode 100644 ExampleSPM/Tests/Info.plist create mode 100644 ExampleSPM/Tests/Tests.swift create mode 100644 LightwehgitCharts/LightwehgitCharts.xcodeproj/project.pbxproj create mode 100644 LightwehgitCharts/LightwehgitCharts.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 LightwehgitCharts/LightwehgitCharts.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100755 LightwehgitCharts/LightwehgitCharts/LightwehgitCharts.docc/LightwehgitCharts.md create mode 100644 LightwehgitCharts/LightwehgitCharts/LightwehgitCharts.h create mode 100644 LightwehgitCharts/LightwehgitChartsTests/LightwehgitChartsTests.swift create mode 100644 LightweightCharts/.gitignore create mode 100644 LightweightCharts/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 LightweightCharts/Assets/.gitkeep delete mode 100644 LightweightCharts/Assets/content-setup.js delete mode 100644 LightweightCharts/Assets/wrapper_functions.js delete mode 100644 LightweightCharts/Classes/.gitkeep delete mode 100644 LightweightCharts/Classes/Extensions/Encodable+JSONString.swift delete mode 100644 LightweightCharts/Classes/Extensions/Int+ColorComponent.swift delete mode 100644 LightweightCharts/Classes/Extensions/NSRegularExpression+Color.swift delete mode 100644 LightweightCharts/Classes/Extensions/String+UniqueString.swift delete mode 100644 LightweightCharts/Classes/Extensions/UIColor+ColorComponents.swift delete mode 100644 LightweightCharts/Classes/Implementations/API/Chart.swift delete mode 100644 LightweightCharts/Classes/Implementations/API/LightweightCharts.swift delete mode 100644 LightweightCharts/Classes/Implementations/API/PriceFormatter.swift delete mode 100644 LightweightCharts/Classes/Implementations/API/PriceLine.swift delete mode 100644 LightweightCharts/Classes/Implementations/API/PriceScale.swift delete mode 100644 LightweightCharts/Classes/Implementations/API/Series/AreaSeries.swift delete mode 100644 LightweightCharts/Classes/Implementations/API/Series/BarSeries.swift delete mode 100644 LightweightCharts/Classes/Implementations/API/Series/CandlestickSeries.swift delete mode 100644 LightweightCharts/Classes/Implementations/API/Series/HistogramSeries.swift delete mode 100644 LightweightCharts/Classes/Implementations/API/Series/LineSeries.swift delete mode 100644 LightweightCharts/Classes/Implementations/API/Series/SeriesApi+Extension.swift delete mode 100644 LightweightCharts/Classes/Implementations/API/Series/SeriesObject.swift delete mode 100644 LightweightCharts/Classes/Implementations/API/TimeScale.swift delete mode 100644 LightweightCharts/Classes/Implementations/JavaScriptEvaluator.swift delete mode 100644 LightweightCharts/Classes/Implementations/JavaScriptMessageProducer.swift delete mode 100644 LightweightCharts/Classes/Implementations/JavaScriptObject.swift delete mode 100644 LightweightCharts/Classes/Implementations/Subscription/MessageHandler.swift delete mode 100644 LightweightCharts/Classes/Implementations/Subscription/Subscription.swift delete mode 100644 LightweightCharts/Classes/Implementations/SyncScriptEvaluating/JavaScriptMethod.swift delete mode 100644 LightweightCharts/Classes/Implementations/SyncScriptEvaluating/JavaScriptSyncMethod.swift delete mode 100644 LightweightCharts/Classes/Implementations/SyncScriptEvaluating/PromptHandler.swift delete mode 100644 LightweightCharts/Classes/Implementations/WebView.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/AutoscaleInfoProvider.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/AxisPressedMouseMoveOptions.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/BarPrice.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/BarsInfo.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/BusinessDay.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/ChartColor.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/ColorType.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Coordinate.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Data/SeriesData/BarData.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Data/SeriesData/HistogramData.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Data/SeriesData/LineData.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Data/SeriesData/SeriesData.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Data/SeriesData/SeriesDataType.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Data/SeriesData/WhitespaceData.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/FromToRange.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/MouseEventParams.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Options/Basics/LastPriceAnimationMode.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Options/Basics/LineStyle.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Options/Basics/LineType.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Options/Basics/LineWidth.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Options/Basics/PriceLineOptions.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Options/Basics/PriceLineSource.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Options/Basics/PriceScaleOptions.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Options/Basics/TimeScaleOptions.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Options/ChartOptions/ChartOptions.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Options/ChartOptions/CrosshairLineOptions.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Options/ChartOptions/CrosshairOptions.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Options/ChartOptions/GridLineOptions.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Options/ChartOptions/GridOptions.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Options/ChartOptions/HandleScaleOptions.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Options/ChartOptions/HandleScrollOptions.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Options/ChartOptions/KineticScrollOptions.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Options/ChartOptions/LayoutOptions.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Options/ChartOptions/LocalizationOptions.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Options/ChartOptions/WatermarkOptions.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Options/SeriesOptions/Options/AreaSeriesOptions.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Options/SeriesOptions/Options/BarSeriesOptions.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Options/SeriesOptions/Options/CandlestickSeriesOptions.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Options/SeriesOptions/Options/HistogramSeriesOptions.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Options/SeriesOptions/Options/LineSeriesOptions.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Options/SeriesOptions/SeriesOptionsCommon.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Point.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/PriceFormat.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/SeriesMarker/SeriesMarker.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/SeriesType.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/SurfaceColor.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/TickMarkFormatter.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/Time.swift delete mode 100644 LightweightCharts/Classes/LightweightChartsModels/TogglableOptions.swift delete mode 100644 LightweightCharts/Classes/Protocols/ChartApi.swift delete mode 100644 LightweightCharts/Classes/Protocols/PriceFormatterApi.swift delete mode 100644 LightweightCharts/Classes/Protocols/PriceLineApi.swift delete mode 100644 LightweightCharts/Classes/Protocols/PriceScaleApi.swift delete mode 100644 LightweightCharts/Classes/Protocols/SeriesApi.swift delete mode 100644 LightweightCharts/Classes/Protocols/TimeScaleApi.swift create mode 100644 LightweightCharts/Package.swift create mode 100644 LightweightCharts/README.md create mode 100644 LightweightCharts/Sources/LightweightCharts/LightweightCharts.swift create mode 100644 LightweightCharts/Tests/LightweightChartsTests/LightweightChartsTests.swift diff --git a/ExampleSPM/.swiftlint.yml b/ExampleSPM/.swiftlint.yml new file mode 100644 index 0000000..644670e --- /dev/null +++ b/ExampleSPM/.swiftlint.yml @@ -0,0 +1,28 @@ +excluded: + - Pods + +included: + - ../LightweightCharts/Classes + +disabled_rules: + - trailing_whitespace + - vertical_whitespace + - identifier_name + +force_cast: warning +force_try: warning +line_length: + warning: 125 + error: 180 + ignores_function_declarations: true +nesting: + type_level: 3 + +warning_threshold: 1 + +custom_rules: + function_declarations_length: + name: "Function Declaration Length" + regex: '^(?=[^\n\r]{190,})[^\n\r]*?func [^\n\r]*$' + message: "Function declaration should be 190 characters or less" + severity: warning diff --git a/ExampleSPM/LightweightCharts.xcodeproj/project.pbxproj b/ExampleSPM/LightweightCharts.xcodeproj/project.pbxproj new file mode 100644 index 0000000..cf3bed6 --- /dev/null +++ b/ExampleSPM/LightweightCharts.xcodeproj/project.pbxproj @@ -0,0 +1,656 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 52; + objects = { + +/* Begin PBXBuildFile section */ + 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD51AFB9204008FA782 /* AppDelegate.swift */; }; + 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Images.xcassets */; }; + 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; }; + 607FACEC1AFB9204008FA782 /* Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACEB1AFB9204008FA782 /* Tests.swift */; }; + 8C8C291824D161F900EC537E /* AddAndRemovePriceLineViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE48520A23A3B3FB0033EE94 /* AddAndRemovePriceLineViewController.swift */; }; + 8C8C291924D1620800EC537E /* PriceLineViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE48520823A3B00E0033EE94 /* PriceLineViewController.swift */; }; + 8C8C291A24D1621500EC537E /* MarkersViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE48520623A39FE50033EE94 /* MarkersViewController.swift */; }; + 8C8C291B24D1625B00EC537E /* FloatingTooltipViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5053E72397AF6D00143B03 /* FloatingTooltipViewController.swift */; }; + 8C8C291C24D162BE00EC537E /* NoPriceScaleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5053E62397AF6D00143B03 /* NoPriceScaleViewController.swift */; }; + 8C8C291D24D162EB00EC537E /* GoToRealtimeButtonViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5053E52397AF6D00143B03 /* GoToRealtimeButtonViewController.swift */; }; + 8C8C291E24D1638A00EC537E /* CandlestickChartViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5053E42397AF6D00143B03 /* CandlestickChartViewController.swift */; }; + 8C8C291F24D163AB00EC537E /* BarChartViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5053E32397AF6D00143B03 /* BarChartViewController.swift */; }; + 8C8C292024D163C500EC537E /* PriceScaleAtLeftViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5053E22397AF6D00143B03 /* PriceScaleAtLeftViewController.swift */; }; + 8C8C292124D163F700EC537E /* InvertedPriceScaleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5053E12397AF6D00143B03 /* InvertedPriceScaleViewController.swift */; }; + 8C8C292224D163FF00EC537E /* PercentagePriceScaleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5053E02397AF6D00143B03 /* PercentagePriceScaleViewController.swift */; }; + 8C8C292324D1641000EC537E /* FitContentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5053DF2397AF6D00143B03 /* FitContentViewController.swift */; }; + 8C8C292424D1642B00EC537E /* IntradayDataViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5053DE2397AF6D00143B03 /* IntradayDataViewController.swift */; }; + 8C8C292524D1643400EC537E /* CustomWatermarkViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5053DC2397AF6D00143B03 /* CustomWatermarkViewController.swift */; }; + 8C8C292624D1646100EC537E /* CustomThemesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5053DB2397AF6D00143B03 /* CustomThemesViewController.swift */; }; + 8C8C292724D1648900EC537E /* RangeSwitcherViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5053DA2397AF6D00143B03 /* RangeSwitcherViewController.swift */; }; + 8C8C292824D164AD00EC537E /* TrackingTooltipViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5053D82397AF6D00143B03 /* TrackingTooltipViewController.swift */; }; + 8C8C292924D164FA00EC537E /* NoTimeScaleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5053D72397AF6D00143B03 /* NoTimeScaleViewController.swift */; }; + 8C8C292A24D1653300EC537E /* CustomPriceFormatterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5053D62397AF6D00143B03 /* CustomPriceFormatterViewController.swift */; }; + 8C8C292B24D1655C00EC537E /* LegendViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5053D52397AF6D00143B03 /* LegendViewController.swift */; }; + 8C8C292C24D1656D00EC537E /* MagnifierTooltipViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5053D42397AF6D00143B03 /* MagnifierTooltipViewController.swift */; }; + 8C8C292D24D1659200EC537E /* LogarithmicPriceScaleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5053D32397AF6D00143B03 /* LogarithmicPriceScaleViewController.swift */; }; + 8C8C292E24D165A200EC537E /* CustomLocaleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5053D22397AF6D00143B03 /* CustomLocaleViewController.swift */; }; + 8C8C292F24D1660400EC537E /* RealtimeEmulationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5053D12397AF6D00143B03 /* RealtimeEmulationViewController.swift */; }; + 8C8C293024D1661D00EC537E /* VolumeStudyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5053D02397AF6D00143B03 /* VolumeStudyViewController.swift */; }; + 8C8C293124D1663500EC537E /* CustomFontFamilyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5053CF2397AF6D00143B03 /* CustomFontFamilyViewController.swift */; }; + 8C8C293224D1666600EC537E /* ThreeLineLegendViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5053CE2397AF6D00143B03 /* ThreeLineLegendViewController.swift */; }; + 8C8C293324D1666F00EC537E /* TableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5053DD2397AF6D00143B03 /* TableViewController.swift */; }; + CE5054042397AF9400143B03 /* TooltipView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5054032397AF9400143B03 /* TooltipView.swift */; }; + FA80E209271773A8001BB011 /* LightweightCharts in Frameworks */ = {isa = PBXBuildFile; productRef = FA80E208271773A8001BB011 /* LightweightCharts */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 607FACE61AFB9204008FA782 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 607FACC81AFB9204008FA782 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 607FACCF1AFB9204008FA782; + remoteInfo = LightweightCharts; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 607FACD01AFB9204008FA782 /* LightweightCharts_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LightweightCharts_Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 607FACD41AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 607FACD51AFB9204008FA782 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 607FACDC1AFB9204008FA782 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 607FACDF1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 607FACE51AFB9204008FA782 /* LightweightCharts_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LightweightCharts_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 607FACEA1AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 607FACEB1AFB9204008FA782 /* Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tests.swift; sourceTree = ""; }; + CE48520623A39FE50033EE94 /* MarkersViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkersViewController.swift; sourceTree = ""; }; + CE48520823A3B00E0033EE94 /* PriceLineViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PriceLineViewController.swift; sourceTree = ""; }; + CE48520A23A3B3FB0033EE94 /* AddAndRemovePriceLineViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddAndRemovePriceLineViewController.swift; sourceTree = ""; }; + CE5053CE2397AF6D00143B03 /* ThreeLineLegendViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThreeLineLegendViewController.swift; sourceTree = ""; }; + CE5053CF2397AF6D00143B03 /* CustomFontFamilyViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomFontFamilyViewController.swift; sourceTree = ""; }; + CE5053D02397AF6D00143B03 /* VolumeStudyViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VolumeStudyViewController.swift; sourceTree = ""; }; + CE5053D12397AF6D00143B03 /* RealtimeEmulationViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RealtimeEmulationViewController.swift; sourceTree = ""; }; + CE5053D22397AF6D00143B03 /* CustomLocaleViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomLocaleViewController.swift; sourceTree = ""; }; + CE5053D32397AF6D00143B03 /* LogarithmicPriceScaleViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LogarithmicPriceScaleViewController.swift; sourceTree = ""; }; + CE5053D42397AF6D00143B03 /* MagnifierTooltipViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MagnifierTooltipViewController.swift; sourceTree = ""; }; + CE5053D52397AF6D00143B03 /* LegendViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LegendViewController.swift; sourceTree = ""; }; + CE5053D62397AF6D00143B03 /* CustomPriceFormatterViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomPriceFormatterViewController.swift; sourceTree = ""; }; + CE5053D72397AF6D00143B03 /* NoTimeScaleViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NoTimeScaleViewController.swift; sourceTree = ""; }; + CE5053D82397AF6D00143B03 /* TrackingTooltipViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrackingTooltipViewController.swift; sourceTree = ""; }; + CE5053DA2397AF6D00143B03 /* RangeSwitcherViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RangeSwitcherViewController.swift; sourceTree = ""; }; + CE5053DB2397AF6D00143B03 /* CustomThemesViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomThemesViewController.swift; sourceTree = ""; }; + CE5053DC2397AF6D00143B03 /* CustomWatermarkViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomWatermarkViewController.swift; sourceTree = ""; }; + CE5053DD2397AF6D00143B03 /* TableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableViewController.swift; sourceTree = ""; }; + CE5053DE2397AF6D00143B03 /* IntradayDataViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IntradayDataViewController.swift; sourceTree = ""; }; + CE5053DF2397AF6D00143B03 /* FitContentViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FitContentViewController.swift; sourceTree = ""; }; + CE5053E02397AF6D00143B03 /* PercentagePriceScaleViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PercentagePriceScaleViewController.swift; sourceTree = ""; }; + CE5053E12397AF6D00143B03 /* InvertedPriceScaleViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InvertedPriceScaleViewController.swift; sourceTree = ""; }; + CE5053E22397AF6D00143B03 /* PriceScaleAtLeftViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PriceScaleAtLeftViewController.swift; sourceTree = ""; }; + CE5053E32397AF6D00143B03 /* BarChartViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BarChartViewController.swift; sourceTree = ""; }; + CE5053E42397AF6D00143B03 /* CandlestickChartViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CandlestickChartViewController.swift; sourceTree = ""; }; + CE5053E52397AF6D00143B03 /* GoToRealtimeButtonViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GoToRealtimeButtonViewController.swift; sourceTree = ""; }; + CE5053E62397AF6D00143B03 /* NoPriceScaleViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NoPriceScaleViewController.swift; sourceTree = ""; }; + CE5053E72397AF6D00143B03 /* FloatingTooltipViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FloatingTooltipViewController.swift; sourceTree = ""; }; + CE5054032397AF9400143B03 /* TooltipView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TooltipView.swift; sourceTree = ""; }; + FA8C04692717737300DEB534 /* LightweightCharts */ = {isa = PBXFileReference; lastKnownFileType = folder; name = LightweightCharts; path = ../LightweightCharts; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 607FACCD1AFB9204008FA782 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + FA80E209271773A8001BB011 /* LightweightCharts in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 607FACE21AFB9204008FA782 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 607FACC71AFB9204008FA782 = { + isa = PBXGroup; + children = ( + FA0FD6FB2717704F0056A052 /* Packages */, + 607FACD21AFB9204008FA782 /* Example for LightweightCharts */, + 607FACE81AFB9204008FA782 /* Tests */, + 607FACD11AFB9204008FA782 /* Products */, + FA00E26E271767DC0040E042 /* Frameworks */, + ); + sourceTree = ""; + }; + 607FACD11AFB9204008FA782 /* Products */ = { + isa = PBXGroup; + children = ( + 607FACD01AFB9204008FA782 /* LightweightCharts_Example.app */, + 607FACE51AFB9204008FA782 /* LightweightCharts_Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 607FACD21AFB9204008FA782 /* Example for LightweightCharts */ = { + isa = PBXGroup; + children = ( + CE5054022397AF9400143B03 /* Views */, + CE5053CD2397AF6D00143B03 /* Example */, + 607FACD51AFB9204008FA782 /* AppDelegate.swift */, + 607FACDC1AFB9204008FA782 /* Images.xcassets */, + 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */, + 607FACD31AFB9204008FA782 /* Supporting Files */, + ); + name = "Example for LightweightCharts"; + path = LightweightCharts; + sourceTree = ""; + }; + 607FACD31AFB9204008FA782 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 607FACD41AFB9204008FA782 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 607FACE81AFB9204008FA782 /* Tests */ = { + isa = PBXGroup; + children = ( + 607FACEB1AFB9204008FA782 /* Tests.swift */, + 607FACE91AFB9204008FA782 /* Supporting Files */, + ); + path = Tests; + sourceTree = ""; + }; + 607FACE91AFB9204008FA782 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 607FACEA1AFB9204008FA782 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + CE5053CD2397AF6D00143B03 /* Example */ = { + isa = PBXGroup; + children = ( + CE5053DD2397AF6D00143B03 /* TableViewController.swift */, + CE5053CE2397AF6D00143B03 /* ThreeLineLegendViewController.swift */, + CE5053CF2397AF6D00143B03 /* CustomFontFamilyViewController.swift */, + CE5053D02397AF6D00143B03 /* VolumeStudyViewController.swift */, + CE5053D12397AF6D00143B03 /* RealtimeEmulationViewController.swift */, + CE5053D22397AF6D00143B03 /* CustomLocaleViewController.swift */, + CE5053D32397AF6D00143B03 /* LogarithmicPriceScaleViewController.swift */, + CE5053D42397AF6D00143B03 /* MagnifierTooltipViewController.swift */, + CE5053D52397AF6D00143B03 /* LegendViewController.swift */, + CE5053D62397AF6D00143B03 /* CustomPriceFormatterViewController.swift */, + CE5053D72397AF6D00143B03 /* NoTimeScaleViewController.swift */, + CE5053D82397AF6D00143B03 /* TrackingTooltipViewController.swift */, + CE5053DA2397AF6D00143B03 /* RangeSwitcherViewController.swift */, + CE5053DB2397AF6D00143B03 /* CustomThemesViewController.swift */, + CE5053DC2397AF6D00143B03 /* CustomWatermarkViewController.swift */, + CE5053DE2397AF6D00143B03 /* IntradayDataViewController.swift */, + CE5053DF2397AF6D00143B03 /* FitContentViewController.swift */, + CE5053E02397AF6D00143B03 /* PercentagePriceScaleViewController.swift */, + CE5053E12397AF6D00143B03 /* InvertedPriceScaleViewController.swift */, + CE5053E22397AF6D00143B03 /* PriceScaleAtLeftViewController.swift */, + CE5053E32397AF6D00143B03 /* BarChartViewController.swift */, + CE5053E42397AF6D00143B03 /* CandlestickChartViewController.swift */, + CE5053E52397AF6D00143B03 /* GoToRealtimeButtonViewController.swift */, + CE5053E62397AF6D00143B03 /* NoPriceScaleViewController.swift */, + CE5053E72397AF6D00143B03 /* FloatingTooltipViewController.swift */, + CE48520623A39FE50033EE94 /* MarkersViewController.swift */, + CE48520823A3B00E0033EE94 /* PriceLineViewController.swift */, + CE48520A23A3B3FB0033EE94 /* AddAndRemovePriceLineViewController.swift */, + ); + path = Example; + sourceTree = ""; + }; + CE5054022397AF9400143B03 /* Views */ = { + isa = PBXGroup; + children = ( + CE5054032397AF9400143B03 /* TooltipView.swift */, + ); + path = Views; + sourceTree = ""; + }; + FA00E26E271767DC0040E042 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; + FA0FD6FB2717704F0056A052 /* Packages */ = { + isa = PBXGroup; + children = ( + FA8C04692717737300DEB534 /* LightweightCharts */, + ); + name = Packages; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 607FACCF1AFB9204008FA782 /* LightweightCharts_Example */ = { + isa = PBXNativeTarget; + buildConfigurationList = 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "LightweightCharts_Example" */; + buildPhases = ( + 607FACCC1AFB9204008FA782 /* Sources */, + 607FACCD1AFB9204008FA782 /* Frameworks */, + 607FACCE1AFB9204008FA782 /* Resources */, + CE4EDA2823A247B800ED8E07 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = LightweightCharts_Example; + packageProductDependencies = ( + FA80E208271773A8001BB011 /* LightweightCharts */, + ); + productName = LightweightCharts; + productReference = 607FACD01AFB9204008FA782 /* LightweightCharts_Example.app */; + productType = "com.apple.product-type.application"; + }; + 607FACE41AFB9204008FA782 /* LightweightCharts_Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "LightweightCharts_Tests" */; + buildPhases = ( + 607FACE11AFB9204008FA782 /* Sources */, + 607FACE21AFB9204008FA782 /* Frameworks */, + 607FACE31AFB9204008FA782 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 607FACE71AFB9204008FA782 /* PBXTargetDependency */, + ); + name = LightweightCharts_Tests; + productName = Tests; + productReference = 607FACE51AFB9204008FA782 /* LightweightCharts_Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 607FACC81AFB9204008FA782 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0830; + LastUpgradeCheck = 1300; + ORGANIZATIONNAME = CocoaPods; + TargetAttributes = { + 607FACCF1AFB9204008FA782 = { + CreatedOnToolsVersion = 6.3.1; + LastSwiftMigration = 0900; + }; + 607FACE41AFB9204008FA782 = { + CreatedOnToolsVersion = 6.3.1; + LastSwiftMigration = 0900; + TestTargetID = 607FACCF1AFB9204008FA782; + }; + }; + }; + buildConfigurationList = 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "LightweightCharts" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 607FACC71AFB9204008FA782; + productRefGroup = 607FACD11AFB9204008FA782 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 607FACCF1AFB9204008FA782 /* LightweightCharts_Example */, + 607FACE41AFB9204008FA782 /* LightweightCharts_Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 607FACCE1AFB9204008FA782 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */, + 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 607FACE31AFB9204008FA782 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + CE4EDA2823A247B800ED8E07 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "#if which swiftlint >/dev/null; then\n #swiftlint\n#else\n # echo \"error: SwiftLint does not exist, install it using brew install swiftlint\"\n #exit 1\n#fi\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 607FACCC1AFB9204008FA782 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8C8C292024D163C500EC537E /* PriceScaleAtLeftViewController.swift in Sources */, + 8C8C292D24D1659200EC537E /* LogarithmicPriceScaleViewController.swift in Sources */, + 8C8C292C24D1656D00EC537E /* MagnifierTooltipViewController.swift in Sources */, + 8C8C291E24D1638A00EC537E /* CandlestickChartViewController.swift in Sources */, + 8C8C292824D164AD00EC537E /* TrackingTooltipViewController.swift in Sources */, + 8C8C292B24D1655C00EC537E /* LegendViewController.swift in Sources */, + 8C8C291D24D162EB00EC537E /* GoToRealtimeButtonViewController.swift in Sources */, + 8C8C291B24D1625B00EC537E /* FloatingTooltipViewController.swift in Sources */, + 8C8C291824D161F900EC537E /* AddAndRemovePriceLineViewController.swift in Sources */, + 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */, + 8C8C292524D1643400EC537E /* CustomWatermarkViewController.swift in Sources */, + 8C8C292424D1642B00EC537E /* IntradayDataViewController.swift in Sources */, + 8C8C292324D1641000EC537E /* FitContentViewController.swift in Sources */, + 8C8C293324D1666F00EC537E /* TableViewController.swift in Sources */, + 8C8C291924D1620800EC537E /* PriceLineViewController.swift in Sources */, + 8C8C292A24D1653300EC537E /* CustomPriceFormatterViewController.swift in Sources */, + 8C8C291A24D1621500EC537E /* MarkersViewController.swift in Sources */, + 8C8C292624D1646100EC537E /* CustomThemesViewController.swift in Sources */, + 8C8C292124D163F700EC537E /* InvertedPriceScaleViewController.swift in Sources */, + 8C8C293024D1661D00EC537E /* VolumeStudyViewController.swift in Sources */, + CE5054042397AF9400143B03 /* TooltipView.swift in Sources */, + 8C8C292E24D165A200EC537E /* CustomLocaleViewController.swift in Sources */, + 8C8C291C24D162BE00EC537E /* NoPriceScaleViewController.swift in Sources */, + 8C8C293124D1663500EC537E /* CustomFontFamilyViewController.swift in Sources */, + 8C8C292724D1648900EC537E /* RangeSwitcherViewController.swift in Sources */, + 8C8C292F24D1660400EC537E /* RealtimeEmulationViewController.swift in Sources */, + 8C8C292924D164FA00EC537E /* NoTimeScaleViewController.swift in Sources */, + 8C8C292224D163FF00EC537E /* PercentagePriceScaleViewController.swift in Sources */, + 8C8C291F24D163AB00EC537E /* BarChartViewController.swift in Sources */, + 8C8C293224D1666600EC537E /* ThreeLineLegendViewController.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 607FACE11AFB9204008FA782 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 607FACEC1AFB9204008FA782 /* Tests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 607FACE71AFB9204008FA782 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 607FACCF1AFB9204008FA782 /* LightweightCharts_Example */; + targetProxy = 607FACE61AFB9204008FA782 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 607FACDF1AFB9204008FA782 /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 607FACED1AFB9204008FA782 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 607FACEE1AFB9204008FA782 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 607FACF01AFB9204008FA782 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = LightweightCharts/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 3.5.0; + MODULE_NAME = ExampleApp; + PRODUCT_BUNDLE_IDENTIFIER = "tradingview.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 607FACF11AFB9204008FA782 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = LightweightCharts/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 3.5.0; + MODULE_NAME = ExampleApp; + PRODUCT_BUNDLE_IDENTIFIER = "tradingview.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 607FACF31AFB9204008FA782 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + FRAMEWORK_SEARCH_PATHS = ( + "$(PLATFORM_DIR)/Developer/Library/Frameworks", + "$(inherited)", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "tradingview.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/LightweightCharts_Example.app/LightweightCharts_Example"; + }; + name = Debug; + }; + 607FACF41AFB9204008FA782 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + FRAMEWORK_SEARCH_PATHS = ( + "$(PLATFORM_DIR)/Developer/Library/Frameworks", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "tradingview.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/LightweightCharts_Example.app/LightweightCharts_Example"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "LightweightCharts" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 607FACED1AFB9204008FA782 /* Debug */, + 607FACEE1AFB9204008FA782 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "LightweightCharts_Example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 607FACF01AFB9204008FA782 /* Debug */, + 607FACF11AFB9204008FA782 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "LightweightCharts_Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 607FACF31AFB9204008FA782 /* Debug */, + 607FACF41AFB9204008FA782 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCSwiftPackageProductDependency section */ + FA80E208271773A8001BB011 /* LightweightCharts */ = { + isa = XCSwiftPackageProductDependency; + productName = LightweightCharts; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = 607FACC81AFB9204008FA782 /* Project object */; +} diff --git a/ExampleSPM/LightweightCharts.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ExampleSPM/LightweightCharts.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..4d5445d --- /dev/null +++ b/ExampleSPM/LightweightCharts.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ExampleSPM/LightweightCharts.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ExampleSPM/LightweightCharts.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ExampleSPM/LightweightCharts.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ExampleSPM/LightweightCharts.xcodeproj/xcshareddata/xcschemes/LightweightCharts-Example.xcscheme b/ExampleSPM/LightweightCharts.xcodeproj/xcshareddata/xcschemes/LightweightCharts-Example.xcscheme new file mode 100644 index 0000000..f477fb7 --- /dev/null +++ b/ExampleSPM/LightweightCharts.xcodeproj/xcshareddata/xcschemes/LightweightCharts-Example.xcscheme @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ExampleSPM/LightweightCharts/AppDelegate.swift b/ExampleSPM/LightweightCharts/AppDelegate.swift new file mode 100644 index 0000000..31e88b4 --- /dev/null +++ b/ExampleSPM/LightweightCharts/AppDelegate.swift @@ -0,0 +1,19 @@ +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + let window = UIWindow() + let viewController = TableViewController() + window.rootViewController = UINavigationController(rootViewController: viewController) + window.makeKeyAndVisible() + self.window = window + return true + } + +} + diff --git a/ExampleSPM/LightweightCharts/Base.lproj/LaunchScreen.xib b/ExampleSPM/LightweightCharts/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..4ca292b --- /dev/null +++ b/ExampleSPM/LightweightCharts/Base.lproj/LaunchScreen.xib @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ExampleSPM/LightweightCharts/Example/AddAndRemovePriceLineViewController.swift b/ExampleSPM/LightweightCharts/Example/AddAndRemovePriceLineViewController.swift new file mode 100644 index 0000000..9b11dcb --- /dev/null +++ b/ExampleSPM/LightweightCharts/Example/AddAndRemovePriceLineViewController.swift @@ -0,0 +1,110 @@ +import UIKit +import LightweightCharts + +class AddAndRemovePriceLineViewController: UIViewController { + + private var chart: LightweightCharts! + private var series: LineSeries! + private var priceLineOne: PriceLine? + private var priceLineTwo: PriceLine? + + override func viewDidLoad() { + super.viewDidLoad() + if #available(iOS 13.0, *) { + view.backgroundColor = .systemBackground + } else { + view.backgroundColor = .white + } + + setupUI() + setupData() + } + + private func setupUI() { + let addButton = UIButton(type: .system) + addButton.setTitle("Add", for: .normal) + addButton.addTarget(self, action: #selector(addButtonTap), for: .touchUpInside) + + let removeButton = UIButton(type: .system) + removeButton.setTitle("Remove", for: .normal) + removeButton.addTarget(self, action: #selector(removeButtonTap), for: .touchUpInside) + + let options = ChartOptions() + let chart = LightweightCharts(options: options) + + view.addSubview(chart) + view.addSubview(addButton) + view.addSubview(removeButton) + + chart.translatesAutoresizingMaskIntoConstraints = false + addButton.translatesAutoresizingMaskIntoConstraints = false + removeButton.translatesAutoresizingMaskIntoConstraints = false + + let padding: CGFloat = 16 + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + addButton.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: padding), + addButton.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: padding), + removeButton.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -padding), + removeButton.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: padding), + chart.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + chart.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + ]) + } else { + NSLayoutConstraint.activate([ + addButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: padding), + addButton.topAnchor.constraint(equalTo: view.topAnchor, constant: padding), + removeButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -padding), + removeButton.topAnchor.constraint(equalTo: view.topAnchor, constant: padding), + chart.leadingAnchor.constraint(equalTo: view.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.trailingAnchor), + chart.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } + NSLayoutConstraint.activate([ + chart.topAnchor.constraint(equalTo: addButton.bottomAnchor, constant: padding) + ]) + self.chart = chart + } + + private func setupData() { + let series = chart.addLineSeries(options: nil) + let data = generateData() + series.setData(data: data) + self.series = series + } + + private func setupPriceLines() { + guard priceLineOne == nil, priceLineTwo == nil else { return } + priceLineOne = series.createPriceLine(options: PriceLineOptions(price: 10)) + priceLineTwo = series.createPriceLine(options: PriceLineOptions(price: 20)) + } + + private func removePriceLines() { + priceLineOne.map { series.removePriceLine(line: $0) } + priceLineTwo.map { series.removePriceLine(line: $0) } + priceLineOne = nil + priceLineTwo = nil + } + + private func generateData() -> [LineData] { + var time = DateComponents(calendar: .current, year: 2018, day: 0).date! + var result: [LineData] = [] + for i in 0..<60 { + time = Date(timeInterval: 60 * 60 * 24, since: time) + let lineData = LineData(time: .utc(timestamp: time.timeIntervalSince1970), value: Double(i)) + result.append(lineData) + } + return result + } + + @objc private func addButtonTap(_ sender: UIButton) { + setupPriceLines() + } + + @objc private func removeButtonTap(_ sender: UIButton) { + removePriceLines() + } + +} diff --git a/ExampleSPM/LightweightCharts/Example/BarChartViewController.swift b/ExampleSPM/LightweightCharts/Example/BarChartViewController.swift new file mode 100644 index 0000000..bf27989 --- /dev/null +++ b/ExampleSPM/LightweightCharts/Example/BarChartViewController.swift @@ -0,0 +1,208 @@ +import UIKit +import LightweightCharts + +class BarChartViewController: UIViewController { + + private var chart: LightweightCharts! + private var series: BarSeries! + + override func viewDidLoad() { + super.viewDidLoad() + if #available(iOS 13.0, *) { + view.backgroundColor = .systemBackground + } else { + view.backgroundColor = .white + } + + setupChart() + setupData() + } + + private func setupChart() { + let options = ChartOptions( + layout: LayoutOptions(backgroundColor: "#ffffff", textColor: "rgba(33, 56, 77, 1)"), + rightPriceScale: VisiblePriceScaleOptions(borderColor: "rgba(197, 203, 206, 1)"), + timeScale: TimeScaleOptions(borderColor: "rgba(197, 203, 206, 1)"), + crosshair: CrosshairOptions(mode: .normal) + ) + let chart = LightweightCharts(options: options) + view.addSubview(chart) + chart.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + ]) + } else { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } + self.chart = chart + } + + private func setupData() { + let options = BarSeriesOptions(upColor: ChartColor(.black), downColor: ChartColor(.black), thinBars: true) + let series = chart.addBarSeries(options: options) + let data = [ + BarData(time: .string("2018-10-19"), open: 180.34, high: 180.99, low: 178.57, close: 179.85), + BarData(time: .string("2018-10-22"), open: 180.82, high: 181.40, low: 177.56, close: 178.75), + BarData(time: .string("2018-10-23"), open: 175.77, high: 179.49, low: 175.44, close: 178.53), + BarData(time: .string("2018-10-24"), open: 178.58, high: 182.37, low: 176.31, close: 176.97), + BarData(time: .string("2018-10-25"), open: 177.52, high: 180.50, low: 176.83, close: 179.07), + BarData(time: .string("2018-10-26"), open: 176.88, high: 177.34, low: 170.91, close: 172.23), + BarData(time: .string("2018-10-29"), open: 173.74, high: 175.99, low: 170.95, close: 173.20), + BarData(time: .string("2018-10-30"), open: 173.16, high: 176.43, low: 172.64, close: 176.24), + BarData(time: .string("2018-10-31"), open: 177.98, high: 178.85, low: 175.59, close: 175.88), + BarData(time: .string("2018-11-01"), open: 176.84, high: 180.86, low: 175.90, close: 180.46), + BarData(time: .string("2018-11-02"), open: 182.47, high: 183.01, low: 177.39, close: 179.93), + BarData(time: .string("2018-11-05"), open: 181.02, high: 182.41, low: 179.30, close: 182.19), + BarData(time: .string("2018-11-06"), open: 181.93, high: 182.65, low: 180.05, close: 182.01), + BarData(time: .string("2018-11-07"), open: 183.79, high: 187.68, low: 182.06, close: 187.23), + BarData(time: .string("2018-11-08"), open: 187.13, high: 188.69, low: 185.72, close: 188.00), + BarData(time: .string("2018-11-09"), open: 188.32, high: 188.48, low: 184.96, close: 185.99), + BarData(time: .string("2018-11-12"), open: 185.23, high: 186.95, low: 179.02, close: 179.43), + BarData(time: .string("2018-11-13"), open: 177.30, high: 181.62, low: 172.85, close: 179.00), + BarData(time: .string("2018-11-14"), open: 182.61, high: 182.90, low: 179.15, close: 179.90), + BarData(time: .string("2018-11-15"), open: 179.01, high: 179.67, low: 173.61, close: 177.36), + BarData(time: .string("2018-11-16"), open: 173.99, high: 177.60, low: 173.51, close: 177.02), + BarData(time: .string("2018-11-19"), open: 176.71, high: 178.88, low: 172.30, close: 173.59), + BarData(time: .string("2018-11-20"), open: 169.25, high: 172.00, low: 167.00, close: 169.05), + BarData(time: .string("2018-11-21"), open: 170.00, high: 170.93, low: 169.15, close: 169.30), + BarData(time: .string("2018-11-23"), open: 169.39, high: 170.33, low: 168.47, close: 168.85), + BarData(time: .string("2018-11-26"), open: 170.20, high: 172.39, low: 168.87, close: 169.82), + BarData(time: .string("2018-11-27"), open: 169.11, high: 173.38, low: 168.82, close: 173.22), + BarData(time: .string("2018-11-28"), open: 172.91, high: 177.65, low: 170.62, close: 177.43), + BarData(time: .string("2018-11-29"), open: 176.80, high: 177.27, low: 174.92, close: 175.66), + BarData(time: .string("2018-11-30"), open: 175.75, high: 180.37, low: 175.11, close: 180.32), + BarData(time: .string("2018-12-03"), open: 183.29, high: 183.50, low: 179.35, close: 181.74), + BarData(time: .string("2018-12-04"), open: 181.06, high: 182.23, low: 174.55, close: 175.30), + BarData(time: .string("2018-12-06"), open: 173.50, high: 176.04, low: 170.46, close: 175.96), + BarData(time: .string("2018-12-07"), open: 175.35, high: 178.36, low: 172.24, close: 172.79), + BarData(time: .string("2018-12-10"), open: 173.39, high: 173.99, low: 167.73, close: 171.69), + BarData(time: .string("2018-12-11"), open: 174.30, high: 175.60, low: 171.24, close: 172.21), + BarData(time: .string("2018-12-12"), open: 173.75, high: 176.87, low: 172.81, close: 174.21), + BarData(time: .string("2018-12-13"), open: 174.31, high: 174.91, low: 172.07, close: 173.87), + BarData(time: .string("2018-12-14"), open: 172.98, high: 175.14, low: 171.95, close: 172.29), + BarData(time: .string("2018-12-17"), open: 171.51, high: 171.99, low: 166.93, close: 167.97), + BarData(time: .string("2018-12-18"), open: 168.90, high: 171.95, low: 168.50, close: 170.04), + BarData(time: .string("2018-12-19"), open: 170.92, high: 174.95, low: 166.77, close: 167.56), + BarData(time: .string("2018-12-20"), open: 166.28, high: 167.31, low: 162.23, close: 164.16), + BarData(time: .string("2018-12-21"), open: 162.81, high: 167.96, low: 160.17, close: 160.48), + BarData(time: .string("2018-12-24"), open: 160.16, high: 161.40, low: 158.09, close: 158.14), + BarData(time: .string("2018-12-26"), open: 159.46, high: 168.28, low: 159.44, close: 168.28), + BarData(time: .string("2018-12-27"), open: 166.44, high: 170.46, low: 163.36, close: 170.32), + BarData(time: .string("2018-12-28"), open: 171.22, high: 173.12, low: 168.60, close: 170.22), + BarData(time: .string("2018-12-31"), open: 171.47, high: 173.24, low: 170.65, close: 171.82), + BarData(time: .string("2019-01-02"), open: 169.71, high: 173.18, low: 169.05, close: 172.41), + BarData(time: .string("2019-01-03"), open: 171.84, high: 171.84, low: 168.21, close: 168.61), + BarData(time: .string("2019-01-04"), open: 170.18, high: 174.74, low: 169.52, close: 173.62), + BarData(time: .string("2019-01-07"), open: 173.83, high: 178.18, low: 173.83, close: 177.04), + BarData(time: .string("2019-01-08"), open: 178.57, high: 179.59, low: 175.61, close: 177.89), + BarData(time: .string("2019-01-09"), open: 177.87, high: 181.27, low: 177.10, close: 179.73), + BarData(time: .string("2019-01-10"), open: 178.03, high: 179.24, low: 176.34, close: 179.06), + BarData(time: .string("2019-01-11"), open: 177.93, high: 180.26, low: 177.12, close: 179.41), + BarData(time: .string("2019-01-14"), open: 177.59, high: 179.23, low: 176.90, close: 178.81), + BarData(time: .string("2019-01-15"), open: 176.08, high: 177.82, low: 175.20, close: 176.47), + BarData(time: .string("2019-01-16"), open: 177.09, high: 177.93, low: 175.86, close: 177.04), + BarData(time: .string("2019-01-17"), open: 174.01, high: 175.46, low: 172.00, close: 174.87), + BarData(time: .string("2019-01-18"), open: 176.98, high: 180.04, low: 176.18, close: 179.58), + BarData(time: .string("2019-01-22"), open: 177.49, high: 178.60, low: 175.36, close: 177.11), + BarData(time: .string("2019-01-23"), open: 176.59, high: 178.06, low: 174.53, close: 176.89), + BarData(time: .string("2019-01-24"), open: 177.00, high: 177.53, low: 175.30, close: 177.29), + BarData(time: .string("2019-01-25"), open: 179.78, high: 180.87, low: 178.61, close: 180.40), + BarData(time: .string("2019-01-28"), open: 178.97, high: 179.99, low: 177.41, close: 179.83), + BarData(time: .string("2019-01-29"), open: 178.96, high: 180.15, low: 178.09, close: 179.69), + BarData(time: .string("2019-01-30"), open: 180.47, high: 184.20, low: 179.78, close: 182.18), + BarData(time: .string("2019-01-31"), open: 181.50, high: 184.67, low: 181.06, close: 183.53), + BarData(time: .string("2019-02-01"), open: 184.03, high: 185.15, low: 182.83, close: 184.37), + BarData(time: .string("2019-02-04"), open: 184.30, high: 186.43, low: 183.84, close: 186.43), + BarData(time: .string("2019-02-05"), open: 186.89, high: 186.99, low: 184.69, close: 186.39), + BarData(time: .string("2019-02-06"), open: 186.69, high: 186.69, low: 184.06, close: 184.72), + BarData(time: .string("2019-02-07"), open: 183.74, high: 184.92, low: 182.45, close: 184.07), + BarData(time: .string("2019-02-08"), open: 183.05, high: 184.58, low: 182.72, close: 184.54), + BarData(time: .string("2019-02-11"), open: 185.00, high: 185.42, low: 182.75, close: 182.92), + BarData(time: .string("2019-02-12"), open: 183.84, high: 186.40, low: 183.52, close: 185.52), + BarData(time: .string("2019-02-13"), open: 186.30, high: 188.68, low: 185.92, close: 188.41), + BarData(time: .string("2019-02-14"), open: 187.50, high: 188.93, low: 186.00, close: 187.71), + BarData(time: .string("2019-02-15"), open: 189.87, high: 192.62, low: 189.05, close: 192.39), + BarData(time: .string("2019-02-19"), open: 191.71, high: 193.19, low: 191.28, close: 192.33), + BarData(time: .string("2019-02-20"), open: 192.39, high: 192.40, low: 191.11, close: 191.85), + BarData(time: .string("2019-02-21"), open: 191.85, high: 192.37, low: 190.61, close: 191.82), + BarData(time: .string("2019-02-22"), open: 191.69, high: 192.54, low: 191.62, close: 192.39), + BarData(time: .string("2019-02-25"), open: 192.75, high: 193.42, low: 189.96, close: 189.98), + BarData(time: .string("2019-02-26"), open: 185.59, high: 188.47, low: 182.80, close: 188.30), + BarData(time: .string("2019-02-27"), open: 187.90, high: 188.50, low: 183.21, close: 183.67), + BarData(time: .string("2019-02-28"), open: 183.60, high: 185.19, low: 183.11, close: 185.14), + BarData(time: .string("2019-03-01"), open: 185.82, high: 186.56, low: 182.86, close: 185.17), + BarData(time: .string("2019-03-04"), open: 186.20, high: 186.24, low: 182.10, close: 183.81), + BarData(time: .string("2019-03-05"), open: 184.24, high: 185.12, low: 183.25, close: 184.00), + BarData(time: .string("2019-03-06"), open: 184.53, high: 184.97, low: 183.84, close: 184.45), + BarData(time: .string("2019-03-07"), open: 184.39, high: 184.62, low: 181.58, close: 182.51), + BarData(time: .string("2019-03-08"), open: 181.49, high: 181.91, low: 179.52, close: 181.23), + BarData(time: .string("2019-03-11"), open: 182.00, high: 183.20, low: 181.20, close: 182.44), + BarData(time: .string("2019-03-12"), open: 183.43, high: 184.27, low: 182.33, close: 184.00), + BarData(time: .string("2019-03-13"), open: 183.24, high: 183.78, low: 181.08, close: 181.14), + BarData(time: .string("2019-03-14"), open: 181.28, high: 181.74, low: 180.50, close: 181.61), + BarData(time: .string("2019-03-15"), open: 182.30, high: 182.49, low: 179.57, close: 182.23), + BarData(time: .string("2019-03-18"), open: 182.53, high: 183.48, low: 182.33, close: 183.42), + BarData(time: .string("2019-03-19"), open: 184.19, high: 185.82, low: 183.48, close: 184.13), + BarData(time: .string("2019-03-20"), open: 184.30, high: 187.12, low: 183.43, close: 186.10), + BarData(time: .string("2019-03-21"), open: 185.50, high: 190.00, low: 185.50, close: 189.97), + BarData(time: .string("2019-03-22"), open: 189.31, high: 192.05, low: 188.67, close: 188.75), + BarData(time: .string("2019-03-25"), open: 188.75, high: 191.71, low: 188.51, close: 189.68), + BarData(time: .string("2019-03-26"), open: 190.69, high: 192.19, low: 188.74, close: 189.34), + BarData(time: .string("2019-03-27"), open: 189.65, high: 191.61, low: 188.39, close: 189.25), + BarData(time: .string("2019-03-28"), open: 189.91, high: 191.40, low: 189.16, close: 190.06), + BarData(time: .string("2019-03-29"), open: 190.85, high: 192.04, low: 190.14, close: 191.89), + BarData(time: .string("2019-04-01"), open: 192.99, high: 195.90, low: 192.85, close: 195.64), + BarData(time: .string("2019-04-02"), open: 195.50, high: 195.50, low: 194.01, close: 194.31), + BarData(time: .string("2019-04-03"), open: 194.98, high: 198.78, low: 194.11, close: 198.61), + BarData(time: .string("2019-04-04"), open: 199.00, high: 200.49, low: 198.02, close: 200.45), + BarData(time: .string("2019-04-05"), open: 200.86, high: 203.13, low: 200.61, close: 202.06), + BarData(time: .string("2019-04-08"), open: 201.37, high: 203.79, low: 201.24, close: 203.55), + BarData(time: .string("2019-04-09"), open: 202.26, high: 202.71, low: 200.46, close: 200.90), + BarData(time: .string("2019-04-10"), open: 201.26, high: 201.60, low: 198.02, close: 199.43), + BarData(time: .string("2019-04-11"), open: 199.90, high: 201.50, low: 199.03, close: 201.48), + BarData(time: .string("2019-04-12"), open: 202.13, high: 204.26, low: 202.13, close: 203.85), + BarData(time: .string("2019-04-15"), open: 204.16, high: 205.14, low: 203.40, close: 204.86), + BarData(time: .string("2019-04-16"), open: 205.25, high: 205.99, low: 204.29, close: 204.47), + BarData(time: .string("2019-04-17"), open: 205.34, high: 206.84, low: 205.32, close: 206.55), + BarData(time: .string("2019-04-18"), open: 206.02, high: 207.78, low: 205.10, close: 205.66), + BarData(time: .string("2019-04-22"), open: 204.11, high: 206.25, low: 204.00, close: 204.78), + BarData(time: .string("2019-04-23"), open: 205.14, high: 207.33, low: 203.43, close: 206.05), + BarData(time: .string("2019-04-24"), open: 206.16, high: 208.29, low: 205.54, close: 206.72), + BarData(time: .string("2019-04-25"), open: 206.01, high: 207.72, low: 205.06, close: 206.50), + BarData(time: .string("2019-04-26"), open: 205.88, high: 206.14, low: 203.34, close: 203.61), + BarData(time: .string("2019-04-29"), open: 203.31, high: 203.80, low: 200.34, close: 202.16), + BarData(time: .string("2019-04-30"), open: 201.55, high: 203.75, low: 200.79, close: 203.70), + BarData(time: .string("2019-05-01"), open: 203.20, high: 203.52, low: 198.66, close: 198.80), + BarData(time: .string("2019-05-02"), open: 199.30, high: 201.06, low: 198.80, close: 201.01), + BarData(time: .string("2019-05-03"), open: 202.00, high: 202.31, low: 200.32, close: 200.56), + BarData(time: .string("2019-05-06"), open: 198.74, high: 199.93, low: 198.31, close: 199.63), + BarData(time: .string("2019-05-07"), open: 196.75, high: 197.65, low: 192.96, close: 194.77), + BarData(time: .string("2019-05-08"), open: 194.49, high: 196.61, low: 193.68, close: 195.17), + BarData(time: .string("2019-05-09"), open: 193.31, high: 195.08, low: 191.59, close: 194.58), + BarData(time: .string("2019-05-10"), open: 193.21, high: 195.49, low: 190.01, close: 194.58), + BarData(time: .string("2019-05-13"), open: 191.00, high: 191.66, low: 189.14, close: 190.34), + BarData(time: .string("2019-05-14"), open: 190.50, high: 192.76, low: 190.01, close: 191.62), + BarData(time: .string("2019-05-15"), open: 190.81, high: 192.81, low: 190.27, close: 191.76), + BarData(time: .string("2019-05-16"), open: 192.47, high: 194.96, low: 192.20, close: 192.38), + BarData(time: .string("2019-05-17"), open: 190.86, high: 194.50, low: 190.75, close: 192.58), + BarData(time: .string("2019-05-20"), open: 191.13, high: 192.86, low: 190.61, close: 190.95), + BarData(time: .string("2019-05-21"), open: 187.13, high: 192.52, low: 186.34, close: 191.45), + BarData(time: .string("2019-05-22"), open: 190.49, high: 192.22, low: 188.05, close: 188.91), + BarData(time: .string("2019-05-23"), open: 188.45, high: 192.54, low: 186.27, close: 192.00), + BarData(time: .string("2019-05-24"), open: 192.54, high: 193.86, low: 190.41, close: 193.59), + BarData(time: .string("2019-05-28"), open: 194.38, high: 196.47, low: 193.75, close: 194.08) + ] + series.setData(data: data) + self.series = series + } + +} diff --git a/ExampleSPM/LightweightCharts/Example/CandlestickChartViewController.swift b/ExampleSPM/LightweightCharts/Example/CandlestickChartViewController.swift new file mode 100644 index 0000000..915acd4 --- /dev/null +++ b/ExampleSPM/LightweightCharts/Example/CandlestickChartViewController.swift @@ -0,0 +1,218 @@ +import UIKit +import LightweightCharts + +class CandlestickChartViewController: UIViewController { + + private var chart: LightweightCharts! + private var series: CandlestickSeries! + + override func viewDidLoad() { + super.viewDidLoad() + if #available(iOS 13.0, *) { + view.backgroundColor = .systemBackground + } else { + view.backgroundColor = .white + } + + setupChart() + setupData() + } + + private func setupChart() { + let options = ChartOptions( + layout: LayoutOptions(backgroundColor: "#000000", textColor: "rgba(255, 255, 255, 0.9)"), + rightPriceScale: VisiblePriceScaleOptions(borderColor: "rgba(197, 203, 206, 0.8)"), + timeScale: TimeScaleOptions(borderColor: "rgba(197, 203, 206, 0.8)"), + crosshair: CrosshairOptions(mode: .normal), + grid: GridOptions( + verticalLines: GridLineOptions(color: "rgba(197, 203, 206, 0.5)"), + horizontalLines: GridLineOptions(color: "rgba(197, 203, 206, 0.5)") + ) + ) + let chart = LightweightCharts(options: options) + view.addSubview(chart) + chart.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + ]) + } else { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } + self.chart = chart + } + + private func setupData() { + let options = CandlestickSeriesOptions( + upColor: "rgba(255, 144, 0, 1)", + downColor: "#000", + borderUpColor: "rgba(255, 144, 0, 1)", + borderDownColor: "rgba(255, 144, 0, 1)", + wickUpColor: "rgba(255, 144, 0, 1)", + wickDownColor: "rgba(255, 144, 0, 1)" + ) + let series = chart.addCandlestickSeries(options: options) + let data = [ + BarData(time: .string("2018-10-19"), open: 180.34, high: 180.99, low: 178.57, close: 179.85), + BarData(time: .string("2018-10-22"), open: 180.82, high: 181.40, low: 177.56, close: 178.75), + BarData(time: .string("2018-10-23"), open: 175.77, high: 179.49, low: 175.44, close: 178.53), + BarData(time: .string("2018-10-24"), open: 178.58, high: 182.37, low: 176.31, close: 176.97), + BarData(time: .string("2018-10-25"), open: 177.52, high: 180.50, low: 176.83, close: 179.07), + BarData(time: .string("2018-10-26"), open: 176.88, high: 177.34, low: 170.91, close: 172.23), + BarData(time: .string("2018-10-29"), open: 173.74, high: 175.99, low: 170.95, close: 173.20), + BarData(time: .string("2018-10-30"), open: 173.16, high: 176.43, low: 172.64, close: 176.24), + BarData(time: .string("2018-10-31"), open: 177.98, high: 178.85, low: 175.59, close: 175.88), + BarData(time: .string("2018-11-01"), open: 176.84, high: 180.86, low: 175.90, close: 180.46), + BarData(time: .string("2018-11-02"), open: 182.47, high: 183.01, low: 177.39, close: 179.93), + BarData(time: .string("2018-11-05"), open: 181.02, high: 182.41, low: 179.30, close: 182.19), + BarData(time: .string("2018-11-06"), open: 181.93, high: 182.65, low: 180.05, close: 182.01), + BarData(time: .string("2018-11-07"), open: 183.79, high: 187.68, low: 182.06, close: 187.23), + BarData(time: .string("2018-11-08"), open: 187.13, high: 188.69, low: 185.72, close: 188.00), + BarData(time: .string("2018-11-09"), open: 188.32, high: 188.48, low: 184.96, close: 185.99), + BarData(time: .string("2018-11-12"), open: 185.23, high: 186.95, low: 179.02, close: 179.43), + BarData(time: .string("2018-11-13"), open: 177.30, high: 181.62, low: 172.85, close: 179.00), + BarData(time: .string("2018-11-14"), open: 182.61, high: 182.90, low: 179.15, close: 179.90), + BarData(time: .string("2018-11-15"), open: 179.01, high: 179.67, low: 173.61, close: 177.36), + BarData(time: .string("2018-11-16"), open: 173.99, high: 177.60, low: 173.51, close: 177.02), + BarData(time: .string("2018-11-19"), open: 176.71, high: 178.88, low: 172.30, close: 173.59), + BarData(time: .string("2018-11-20"), open: 169.25, high: 172.00, low: 167.00, close: 169.05), + BarData(time: .string("2018-11-21"), open: 170.00, high: 170.93, low: 169.15, close: 169.30), + BarData(time: .string("2018-11-23"), open: 169.39, high: 170.33, low: 168.47, close: 168.85), + BarData(time: .string("2018-11-26"), open: 170.20, high: 172.39, low: 168.87, close: 169.82), + BarData(time: .string("2018-11-27"), open: 169.11, high: 173.38, low: 168.82, close: 173.22), + BarData(time: .string("2018-11-28"), open: 172.91, high: 177.65, low: 170.62, close: 177.43), + BarData(time: .string("2018-11-29"), open: 176.80, high: 177.27, low: 174.92, close: 175.66), + BarData(time: .string("2018-11-30"), open: 175.75, high: 180.37, low: 175.11, close: 180.32), + BarData(time: .string("2018-12-03"), open: 183.29, high: 183.50, low: 179.35, close: 181.74), + BarData(time: .string("2018-12-04"), open: 181.06, high: 182.23, low: 174.55, close: 175.30), + BarData(time: .string("2018-12-06"), open: 173.50, high: 176.04, low: 170.46, close: 175.96), + BarData(time: .string("2018-12-07"), open: 175.35, high: 178.36, low: 172.24, close: 172.79), + BarData(time: .string("2018-12-10"), open: 173.39, high: 173.99, low: 167.73, close: 171.69), + BarData(time: .string("2018-12-11"), open: 174.30, high: 175.60, low: 171.24, close: 172.21), + BarData(time: .string("2018-12-12"), open: 173.75, high: 176.87, low: 172.81, close: 174.21), + BarData(time: .string("2018-12-13"), open: 174.31, high: 174.91, low: 172.07, close: 173.87), + BarData(time: .string("2018-12-14"), open: 172.98, high: 175.14, low: 171.95, close: 172.29), + BarData(time: .string("2018-12-17"), open: 171.51, high: 171.99, low: 166.93, close: 167.97), + BarData(time: .string("2018-12-18"), open: 168.90, high: 171.95, low: 168.50, close: 170.04), + BarData(time: .string("2018-12-19"), open: 170.92, high: 174.95, low: 166.77, close: 167.56), + BarData(time: .string("2018-12-20"), open: 166.28, high: 167.31, low: 162.23, close: 164.16), + BarData(time: .string("2018-12-21"), open: 162.81, high: 167.96, low: 160.17, close: 160.48), + BarData(time: .string("2018-12-24"), open: 160.16, high: 161.40, low: 158.09, close: 158.14), + BarData(time: .string("2018-12-26"), open: 159.46, high: 168.28, low: 159.44, close: 168.28), + BarData(time: .string("2018-12-27"), open: 166.44, high: 170.46, low: 163.36, close: 170.32), + BarData(time: .string("2018-12-28"), open: 171.22, high: 173.12, low: 168.60, close: 170.22), + BarData(time: .string("2018-12-31"), open: 171.47, high: 173.24, low: 170.65, close: 171.82), + BarData(time: .string("2019-01-02"), open: 169.71, high: 173.18, low: 169.05, close: 172.41), + BarData(time: .string("2019-01-03"), open: 171.84, high: 171.84, low: 168.21, close: 168.61), + BarData(time: .string("2019-01-04"), open: 170.18, high: 174.74, low: 169.52, close: 173.62), + BarData(time: .string("2019-01-07"), open: 173.83, high: 178.18, low: 173.83, close: 177.04), + BarData(time: .string("2019-01-08"), open: 178.57, high: 179.59, low: 175.61, close: 177.89), + BarData(time: .string("2019-01-09"), open: 177.87, high: 181.27, low: 177.10, close: 179.73), + BarData(time: .string("2019-01-10"), open: 178.03, high: 179.24, low: 176.34, close: 179.06), + BarData(time: .string("2019-01-11"), open: 177.93, high: 180.26, low: 177.12, close: 179.41), + BarData(time: .string("2019-01-14"), open: 177.59, high: 179.23, low: 176.90, close: 178.81), + BarData(time: .string("2019-01-15"), open: 176.08, high: 177.82, low: 175.20, close: 176.47), + BarData(time: .string("2019-01-16"), open: 177.09, high: 177.93, low: 175.86, close: 177.04), + BarData(time: .string("2019-01-17"), open: 174.01, high: 175.46, low: 172.00, close: 174.87), + BarData(time: .string("2019-01-18"), open: 176.98, high: 180.04, low: 176.18, close: 179.58), + BarData(time: .string("2019-01-22"), open: 177.49, high: 178.60, low: 175.36, close: 177.11), + BarData(time: .string("2019-01-23"), open: 176.59, high: 178.06, low: 174.53, close: 176.89), + BarData(time: .string("2019-01-24"), open: 177.00, high: 177.53, low: 175.30, close: 177.29), + BarData(time: .string("2019-01-25"), open: 179.78, high: 180.87, low: 178.61, close: 180.40), + BarData(time: .string("2019-01-28"), open: 178.97, high: 179.99, low: 177.41, close: 179.83), + BarData(time: .string("2019-01-29"), open: 178.96, high: 180.15, low: 178.09, close: 179.69), + BarData(time: .string("2019-01-30"), open: 180.47, high: 184.20, low: 179.78, close: 182.18), + BarData(time: .string("2019-01-31"), open: 181.50, high: 184.67, low: 181.06, close: 183.53), + BarData(time: .string("2019-02-01"), open: 184.03, high: 185.15, low: 182.83, close: 184.37), + BarData(time: .string("2019-02-04"), open: 184.30, high: 186.43, low: 183.84, close: 186.43), + BarData(time: .string("2019-02-05"), open: 186.89, high: 186.99, low: 184.69, close: 186.39), + BarData(time: .string("2019-02-06"), open: 186.69, high: 186.69, low: 184.06, close: 184.72), + BarData(time: .string("2019-02-07"), open: 183.74, high: 184.92, low: 182.45, close: 184.07), + BarData(time: .string("2019-02-08"), open: 183.05, high: 184.58, low: 182.72, close: 184.54), + BarData(time: .string("2019-02-11"), open: 185.00, high: 185.42, low: 182.75, close: 182.92), + BarData(time: .string("2019-02-12"), open: 183.84, high: 186.40, low: 183.52, close: 185.52), + BarData(time: .string("2019-02-13"), open: 186.30, high: 188.68, low: 185.92, close: 188.41), + BarData(time: .string("2019-02-14"), open: 187.50, high: 188.93, low: 186.00, close: 187.71), + BarData(time: .string("2019-02-15"), open: 189.87, high: 192.62, low: 189.05, close: 192.39), + BarData(time: .string("2019-02-19"), open: 191.71, high: 193.19, low: 191.28, close: 192.33), + BarData(time: .string("2019-02-20"), open: 192.39, high: 192.40, low: 191.11, close: 191.85), + BarData(time: .string("2019-02-21"), open: 191.85, high: 192.37, low: 190.61, close: 191.82), + BarData(time: .string("2019-02-22"), open: 191.69, high: 192.54, low: 191.62, close: 192.39), + BarData(time: .string("2019-02-25"), open: 192.75, high: 193.42, low: 189.96, close: 189.98), + BarData(time: .string("2019-02-26"), open: 185.59, high: 188.47, low: 182.80, close: 188.30), + BarData(time: .string("2019-02-27"), open: 187.90, high: 188.50, low: 183.21, close: 183.67), + BarData(time: .string("2019-02-28"), open: 183.60, high: 185.19, low: 183.11, close: 185.14), + BarData(time: .string("2019-03-01"), open: 185.82, high: 186.56, low: 182.86, close: 185.17), + BarData(time: .string("2019-03-04"), open: 186.20, high: 186.24, low: 182.10, close: 183.81), + BarData(time: .string("2019-03-05"), open: 184.24, high: 185.12, low: 183.25, close: 184.00), + BarData(time: .string("2019-03-06"), open: 184.53, high: 184.97, low: 183.84, close: 184.45), + BarData(time: .string("2019-03-07"), open: 184.39, high: 184.62, low: 181.58, close: 182.51), + BarData(time: .string("2019-03-08"), open: 181.49, high: 181.91, low: 179.52, close: 181.23), + BarData(time: .string("2019-03-11"), open: 182.00, high: 183.20, low: 181.20, close: 182.44), + BarData(time: .string("2019-03-12"), open: 183.43, high: 184.27, low: 182.33, close: 184.00), + BarData(time: .string("2019-03-13"), open: 183.24, high: 183.78, low: 181.08, close: 181.14), + BarData(time: .string("2019-03-14"), open: 181.28, high: 181.74, low: 180.50, close: 181.61), + BarData(time: .string("2019-03-15"), open: 182.30, high: 182.49, low: 179.57, close: 182.23), + BarData(time: .string("2019-03-18"), open: 182.53, high: 183.48, low: 182.33, close: 183.42), + BarData(time: .string("2019-03-19"), open: 184.19, high: 185.82, low: 183.48, close: 184.13), + BarData(time: .string("2019-03-20"), open: 184.30, high: 187.12, low: 183.43, close: 186.10), + BarData(time: .string("2019-03-21"), open: 185.50, high: 190.00, low: 185.50, close: 189.97), + BarData(time: .string("2019-03-22"), open: 189.31, high: 192.05, low: 188.67, close: 188.75), + BarData(time: .string("2019-03-25"), open: 188.75, high: 191.71, low: 188.51, close: 189.68), + BarData(time: .string("2019-03-26"), open: 190.69, high: 192.19, low: 188.74, close: 189.34), + BarData(time: .string("2019-03-27"), open: 189.65, high: 191.61, low: 188.39, close: 189.25), + BarData(time: .string("2019-03-28"), open: 189.91, high: 191.40, low: 189.16, close: 190.06), + BarData(time: .string("2019-03-29"), open: 190.85, high: 192.04, low: 190.14, close: 191.89), + BarData(time: .string("2019-04-01"), open: 192.99, high: 195.90, low: 192.85, close: 195.64), + BarData(time: .string("2019-04-02"), open: 195.50, high: 195.50, low: 194.01, close: 194.31), + BarData(time: .string("2019-04-03"), open: 194.98, high: 198.78, low: 194.11, close: 198.61), + BarData(time: .string("2019-04-04"), open: 199.00, high: 200.49, low: 198.02, close: 200.45), + BarData(time: .string("2019-04-05"), open: 200.86, high: 203.13, low: 200.61, close: 202.06), + BarData(time: .string("2019-04-08"), open: 201.37, high: 203.79, low: 201.24, close: 203.55), + BarData(time: .string("2019-04-09"), open: 202.26, high: 202.71, low: 200.46, close: 200.90), + BarData(time: .string("2019-04-10"), open: 201.26, high: 201.60, low: 198.02, close: 199.43), + BarData(time: .string("2019-04-11"), open: 199.90, high: 201.50, low: 199.03, close: 201.48), + BarData(time: .string("2019-04-12"), open: 202.13, high: 204.26, low: 202.13, close: 203.85), + BarData(time: .string("2019-04-15"), open: 204.16, high: 205.14, low: 203.40, close: 204.86), + BarData(time: .string("2019-04-16"), open: 205.25, high: 205.99, low: 204.29, close: 204.47), + BarData(time: .string("2019-04-17"), open: 205.34, high: 206.84, low: 205.32, close: 206.55), + BarData(time: .string("2019-04-18"), open: 206.02, high: 207.78, low: 205.10, close: 205.66), + BarData(time: .string("2019-04-22"), open: 204.11, high: 206.25, low: 204.00, close: 204.78), + BarData(time: .string("2019-04-23"), open: 205.14, high: 207.33, low: 203.43, close: 206.05), + BarData(time: .string("2019-04-24"), open: 206.16, high: 208.29, low: 205.54, close: 206.72), + BarData(time: .string("2019-04-25"), open: 206.01, high: 207.72, low: 205.06, close: 206.50), + BarData(time: .string("2019-04-26"), open: 205.88, high: 206.14, low: 203.34, close: 203.61), + BarData(time: .string("2019-04-29"), open: 203.31, high: 203.80, low: 200.34, close: 202.16), + BarData(time: .string("2019-04-30"), open: 201.55, high: 203.75, low: 200.79, close: 203.70), + BarData(time: .string("2019-05-01"), open: 203.20, high: 203.52, low: 198.66, close: 198.80), + BarData(time: .string("2019-05-02"), open: 199.30, high: 201.06, low: 198.80, close: 201.01), + BarData(time: .string("2019-05-03"), open: 202.00, high: 202.31, low: 200.32, close: 200.56), + BarData(time: .string("2019-05-06"), open: 198.74, high: 199.93, low: 198.31, close: 199.63), + BarData(time: .string("2019-05-07"), open: 196.75, high: 197.65, low: 192.96, close: 194.77), + BarData(time: .string("2019-05-08"), open: 194.49, high: 196.61, low: 193.68, close: 195.17), + BarData(time: .string("2019-05-09"), open: 193.31, high: 195.08, low: 191.59, close: 194.58), + BarData(time: .string("2019-05-10"), open: 193.21, high: 195.49, low: 190.01, close: 194.58), + BarData(time: .string("2019-05-13"), open: 191.00, high: 191.66, low: 189.14, close: 190.34), + BarData(time: .string("2019-05-14"), open: 190.50, high: 192.76, low: 190.01, close: 191.62), + BarData(time: .string("2019-05-15"), open: 190.81, high: 192.81, low: 190.27, close: 191.76), + BarData(time: .string("2019-05-16"), open: 192.47, high: 194.96, low: 192.20, close: 192.38), + BarData(time: .string("2019-05-17"), open: 190.86, high: 194.50, low: 190.75, close: 192.58), + BarData(time: .string("2019-05-20"), open: 191.13, high: 192.86, low: 190.61, close: 190.95), + BarData(time: .string("2019-05-21"), open: 187.13, high: 192.52, low: 186.34, close: 191.45), + BarData(time: .string("2019-05-22"), open: 190.49, high: 192.22, low: 188.05, close: 188.91), + BarData(time: .string("2019-05-23"), open: 188.45, high: 192.54, low: 186.27, close: 192.00), + BarData(time: .string("2019-05-24"), open: 192.54, high: 193.86, low: 190.41, close: 193.59) + ] + series.setData(data: data) + self.series = series + } + +} diff --git a/ExampleSPM/LightweightCharts/Example/CustomFontFamilyViewController.swift b/ExampleSPM/LightweightCharts/Example/CustomFontFamilyViewController.swift new file mode 100644 index 0000000..0573bb3 --- /dev/null +++ b/ExampleSPM/LightweightCharts/Example/CustomFontFamilyViewController.swift @@ -0,0 +1,235 @@ +import UIKit +import LightweightCharts + +class CustomFontFamilyViewController: UIViewController { + + private var chart: LightweightCharts! + private var series: AreaSeries! + private let fonts = ["Helvetica", "Trebuchet MS", "Serif"] + + override func viewDidLoad() { + super.viewDidLoad() + if #available(iOS 13.0, *) { + view.backgroundColor = .systemBackground + } else { + view.backgroundColor = .white + } + + setupUI() + setupData() + } + + private func setupUI() { + let segmentedControl = UISegmentedControl(items: fonts) + segmentedControl.addTarget(self, action: #selector(valueChanged), for: .valueChanged) + view.addSubview(segmentedControl) + segmentedControl.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + segmentedControl.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor), + segmentedControl.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + ]) + } else { + NSLayoutConstraint.activate([ + segmentedControl.centerXAnchor.constraint(equalTo: view.centerXAnchor), + segmentedControl.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } + + let options = ChartOptions( + layout: LayoutOptions(fontFamily: fonts[0]), + rightPriceScale: VisiblePriceScaleOptions(borderColor: "rgba(197, 203, 206, 1)"), + timeScale: TimeScaleOptions(borderColor: "rgba(197, 203, 206, 1)") + ) + let chart = LightweightCharts(options: options) + view.addSubview(chart) + chart.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + chart.bottomAnchor.constraint(equalTo: segmentedControl.topAnchor, constant: -16) + ]) + } else { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.topAnchor), + chart.bottomAnchor.constraint(equalTo: segmentedControl.topAnchor, constant: -16) + ]) + } + self.chart = chart + + segmentedControl.selectedSegmentIndex = 0 + } + + private func setupData() { + let options = AreaSeriesOptions( + topColor: "rgba(33, 150, 243, 0.56)", + bottomColor: "rgba(33, 150, 243, 0.04)", + lineColor: "rgba(33, 150, 243, 1)", + lineWidth: .two + ) + let series = chart.addAreaSeries(options: options) + let data = [ + LineData(time: .string("2018-10-19"), value: 46.33), + LineData(time: .string("2018-10-22"), value: 45.97), + LineData(time: .string("2018-10-23"), value: 46.36), + LineData(time: .string("2018-10-24"), value: 46.73), + LineData(time: .string("2018-10-25"), value: 46.51), + LineData(time: .string("2018-10-26"), value: 45.92), + LineData(time: .string("2018-10-29"), value: 46.46), + LineData(time: .string("2018-10-30"), value: 47.63), + LineData(time: .string("2018-10-31"), value: 47.88), + LineData(time: .string("2018-11-01"), value: 47.74), + LineData(time: .string("2018-11-02"), value: 48.00), + LineData(time: .string("2018-11-05"), value: 48.69), + LineData(time: .string("2018-11-06"), value: 49.11), + LineData(time: .string("2018-11-07"), value: 49.37), + LineData(time: .string("2018-11-08"), value: 49.33), + LineData(time: .string("2018-11-09"), value: 49.68), + LineData(time: .string("2018-11-12"), value: 49.87), + LineData(time: .string("2018-11-13"), value: 49.86), + LineData(time: .string("2018-11-14"), value: 49.76), + LineData(time: .string("2018-11-15"), value: 49.74), + LineData(time: .string("2018-11-16"), value: 50.17), + LineData(time: .string("2018-11-19"), value: 50.51), + LineData(time: .string("2018-11-20"), value: 49.38), + LineData(time: .string("2018-11-21"), value: 48.73), + LineData(time: .string("2018-11-23"), value: 49.02), + LineData(time: .string("2018-11-26"), value: 48.87), + LineData(time: .string("2018-11-27"), value: 49.37), + LineData(time: .string("2018-11-28"), value: 49.71), + LineData(time: .string("2018-11-29"), value: 48.98), + LineData(time: .string("2018-11-30"), value: 50.40), + LineData(time: .string("2018-12-03"), value: 49.69), + LineData(time: .string("2018-12-04"), value: 49.58), + LineData(time: .string("2018-12-06"), value: 49.38), + LineData(time: .string("2018-12-07"), value: 49.09), + LineData(time: .string("2018-12-10"), value: 49.24), + LineData(time: .string("2018-12-11"), value: 49.54), + LineData(time: .string("2018-12-12"), value: 49.22), + LineData(time: .string("2018-12-13"), value: 49.47), + LineData(time: .string("2018-12-14"), value: 49.34), + LineData(time: .string("2018-12-17"), value: 48.33), + LineData(time: .string("2018-12-18"), value: 48.32), + LineData(time: .string("2018-12-19"), value: 47.90), + LineData(time: .string("2018-12-20"), value: 47.54), + LineData(time: .string("2018-12-21"), value: 47.57), + LineData(time: .string("2018-12-24"), value: 45.96), + LineData(time: .string("2018-12-26"), value: 46.94), + LineData(time: .string("2018-12-27"), value: 47.53), + LineData(time: .string("2018-12-28"), value: 47.20), + LineData(time: .string("2018-12-31"), value: 47.35), + LineData(time: .string("2019-01-02"), value: 46.93), + LineData(time: .string("2019-01-03"), value: 46.64), + LineData(time: .string("2019-01-04"), value: 47.57), + LineData(time: .string("2019-01-07"), value: 46.95), + LineData(time: .string("2019-01-08"), value: 47.48), + LineData(time: .string("2019-01-09"), value: 46.57), + LineData(time: .string("2019-01-10"), value: 47.07), + LineData(time: .string("2019-01-11"), value: 47.34), + LineData(time: .string("2019-01-14"), value: 47.15), + LineData(time: .string("2019-01-15"), value: 47.57), + LineData(time: .string("2019-01-16"), value: 46.92), + LineData(time: .string("2019-01-17"), value: 47.06), + LineData(time: .string("2019-01-18"), value: 47.61), + LineData(time: .string("2019-01-22"), value: 47.72), + LineData(time: .string("2019-01-23"), value: 48.27), + LineData(time: .string("2019-01-24"), value: 47.69), + LineData(time: .string("2019-01-25"), value: 47.37), + LineData(time: .string("2019-01-28"), value: 47.17), + LineData(time: .string("2019-01-29"), value: 47.40), + LineData(time: .string("2019-01-30"), value: 47.86), + LineData(time: .string("2019-01-31"), value: 48.13), + LineData(time: .string("2019-02-01"), value: 48.70), + LineData(time: .string("2019-02-04"), value: 49.25), + LineData(time: .string("2019-02-05"), value: 49.26), + LineData(time: .string("2019-02-06"), value: 49.26), + LineData(time: .string("2019-02-07"), value: 49.42), + LineData(time: .string("2019-02-08"), value: 49.50), + LineData(time: .string("2019-02-11"), value: 49.61), + LineData(time: .string("2019-02-12"), value: 49.66), + LineData(time: .string("2019-02-13"), value: 49.79), + LineData(time: .string("2019-02-14"), value: 45.59), + LineData(time: .string("2019-02-15"), value: 45.24), + LineData(time: .string("2019-02-19"), value: 44.83), + LineData(time: .string("2019-02-20"), value: 45.10), + LineData(time: .string("2019-02-21"), value: 45.86), + LineData(time: .string("2019-02-22"), value: 45.28), + LineData(time: .string("2019-02-25"), value: 44.94), + LineData(time: .string("2019-02-26"), value: 44.69), + LineData(time: .string("2019-02-27"), value: 44.94), + LineData(time: .string("2019-02-28"), value: 45.34), + LineData(time: .string("2019-03-01"), value: 45.38), + LineData(time: .string("2019-03-04"), value: 45.65), + LineData(time: .string("2019-03-05"), value: 45.60), + LineData(time: .string("2019-03-06"), value: 45.45), + LineData(time: .string("2019-03-07"), value: 45.28), + LineData(time: .string("2019-03-08"), value: 44.84), + LineData(time: .string("2019-03-11"), value: 46.18), + LineData(time: .string("2019-03-12"), value: 46.05), + LineData(time: .string("2019-03-13"), value: 46.22), + LineData(time: .string("2019-03-14"), value: 45.70), + LineData(time: .string("2019-03-15"), value: 45.30), + LineData(time: .string("2019-03-18"), value: 45.41), + LineData(time: .string("2019-03-19"), value: 45.56), + LineData(time: .string("2019-03-20"), value: 45.53), + LineData(time: .string("2019-03-21"), value: 45.51), + LineData(time: .string("2019-03-22"), value: 45.93), + LineData(time: .string("2019-03-25"), value: 46.03), + LineData(time: .string("2019-03-26"), value: 46.64), + LineData(time: .string("2019-03-27"), value: 46.61), + LineData(time: .string("2019-03-28"), value: 46.58), + LineData(time: .string("2019-03-29"), value: 46.86), + LineData(time: .string("2019-04-01"), value: 46.72), + LineData(time: .string("2019-04-02"), value: 46.57), + LineData(time: .string("2019-04-03"), value: 46.18), + LineData(time: .string("2019-04-04"), value: 46.48), + LineData(time: .string("2019-04-05"), value: 46.47), + LineData(time: .string("2019-04-08"), value: 46.55), + LineData(time: .string("2019-04-09"), value: 46.67), + LineData(time: .string("2019-04-10"), value: 46.64), + LineData(time: .string("2019-04-11"), value: 46.71), + LineData(time: .string("2019-04-12"), value: 46.74), + LineData(time: .string("2019-04-15"), value: 47.00), + LineData(time: .string("2019-04-16"), value: 46.95), + LineData(time: .string("2019-04-17"), value: 47.28), + LineData(time: .string("2019-04-18"), value: 47.48), + LineData(time: .string("2019-04-22"), value: 47.40), + LineData(time: .string("2019-04-23"), value: 48.21), + LineData(time: .string("2019-04-24"), value: 47.98), + LineData(time: .string("2019-04-25"), value: 47.84), + LineData(time: .string("2019-04-26"), value: 48.26), + LineData(time: .string("2019-04-29"), value: 48.42), + LineData(time: .string("2019-04-30"), value: 49.06), + LineData(time: .string("2019-05-01"), value: 48.59), + LineData(time: .string("2019-05-02"), value: 48.39), + LineData(time: .string("2019-05-03"), value: 48.72), + LineData(time: .string("2019-05-06"), value: 48.47), + LineData(time: .string("2019-05-07"), value: 48.00), + LineData(time: .string("2019-05-08"), value: 47.85), + LineData(time: .string("2019-05-09"), value: 47.40), + LineData(time: .string("2019-05-10"), value: 48.19), + LineData(time: .string("2019-05-13"), value: 48.05), + LineData(time: .string("2019-05-14"), value: 48.69), + LineData(time: .string("2019-05-15"), value: 49.18), + LineData(time: .string("2019-05-16"), value: 49.58), + LineData(time: .string("2019-05-17"), value: 49.20), + LineData(time: .string("2019-05-20"), value: 48.85), + LineData(time: .string("2019-05-21"), value: 48.60), + LineData(time: .string("2019-05-22"), value: 49.65), + LineData(time: .string("2019-05-23"), value: 49.85), + LineData(time: .string("2019-05-24"), value: 49.61), + LineData(time: .string("2019-05-28"), value: 49.24) + ] + series.setData(data: data) + self.series = series + } + + @objc private func valueChanged(_ sender: UISegmentedControl) { + chart.applyOptions(options: ChartOptions(layout: LayoutOptions(fontFamily: fonts[sender.selectedSegmentIndex]))) + } + +} diff --git a/ExampleSPM/LightweightCharts/Example/CustomLocaleViewController.swift b/ExampleSPM/LightweightCharts/Example/CustomLocaleViewController.swift new file mode 100644 index 0000000..0f73a0f --- /dev/null +++ b/ExampleSPM/LightweightCharts/Example/CustomLocaleViewController.swift @@ -0,0 +1,230 @@ +import UIKit +import LightweightCharts + +class CustomLocaleViewController: UIViewController { + + private var chart: LightweightCharts! + private var series: LineSeries! + private let locales = ["es-ES", "en-US", "ja-JP"] + + override func viewDidLoad() { + super.viewDidLoad() + if #available(iOS 13.0, *) { + view.backgroundColor = .systemBackground + } else { + view.backgroundColor = .white + } + + setupUI() + setupData() + } + + private func setupUI() { + let segmentedControl = UISegmentedControl(items: locales) + segmentedControl.addTarget(self, action: #selector(valueChanged), for: .valueChanged) + view.addSubview(segmentedControl) + segmentedControl.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + segmentedControl.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor), + segmentedControl.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + ]) + } else { + NSLayoutConstraint.activate([ + segmentedControl.centerXAnchor.constraint(equalTo: view.centerXAnchor), + segmentedControl.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } + + let options = ChartOptions( + localization: LocalizationOptions(locale: locales[0]) + ) + let chart = LightweightCharts(options: options) + view.addSubview(chart) + chart.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + chart.bottomAnchor.constraint(equalTo: segmentedControl.topAnchor, constant: -16) + ]) + } else { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.topAnchor), + chart.bottomAnchor.constraint(equalTo: segmentedControl.topAnchor, constant: -16) + ]) + } + self.chart = chart + + segmentedControl.selectedSegmentIndex = 0 + } + + private func setupData() { + let series = chart.addLineSeries(options: nil) + let data = [ + LineData(time: .string("2018-10-19"), value: 52.89), + LineData(time: .string("2018-10-22"), value: 51.65), + LineData(time: .string("2018-10-23"), value: 51.56), + LineData(time: .string("2018-10-24"), value: 50.19), + LineData(time: .string("2018-10-25"), value: 51.86), + LineData(time: .string("2018-10-26"), value: 51.25), + LineData(time: .string("2018-10-29"), value: 52.23), + LineData(time: .string("2018-10-30"), value: 52.69), + LineData(time: .string("2018-10-31"), value: 53.23), + LineData(time: .string("2018-11-01"), value: 53.56), + LineData(time: .string("2018-11-02"), value: 53.61), + LineData(time: .string("2018-11-05"), value: 53.66), + LineData(time: .string("2018-11-06"), value: 53.55), + LineData(time: .string("2018-11-07"), value: 53.58), + LineData(time: .string("2018-11-08"), value: 53.16), + LineData(time: .string("2018-11-09"), value: 53.04), + LineData(time: .string("2018-11-12"), value: 52.35), + LineData(time: .string("2018-11-13"), value: 52.74), + LineData(time: .string("2018-11-14"), value: 52.15), + LineData(time: .string("2018-11-15"), value: 52.82), + LineData(time: .string("2018-11-16"), value: 52.94), + LineData(time: .string("2018-11-19"), value: 53.32), + LineData(time: .string("2018-11-20"), value: 52.54), + LineData(time: .string("2018-11-21"), value: 52.43), + LineData(time: .string("2018-11-23"), value: 51.83), + LineData(time: .string("2018-11-26"), value: 52.88), + LineData(time: .string("2018-11-27"), value: 53.19), + LineData(time: .string("2018-11-28"), value: 54.35), + LineData(time: .string("2018-11-29"), value: 54.04), + LineData(time: .string("2018-11-30"), value: 54.28), + LineData(time: .string("2018-12-03"), value: 54.24), + LineData(time: .string("2018-12-04"), value: 51.78), + LineData(time: .string("2018-12-06"), value: 51.09), + LineData(time: .string("2018-12-07"), value: 50.26), + LineData(time: .string("2018-12-10"), value: 48.80), + LineData(time: .string("2018-12-11"), value: 47.76), + LineData(time: .string("2018-12-12"), value: 47.74), + LineData(time: .string("2018-12-13"), value: 47.03), + LineData(time: .string("2018-12-14"), value: 46.54), + LineData(time: .string("2018-12-17"), value: 46.61), + LineData(time: .string("2018-12-18"), value: 46.52), + LineData(time: .string("2018-12-19"), value: 45.67), + LineData(time: .string("2018-12-20"), value: 46.04), + LineData(time: .string("2018-12-21"), value: 45.12), + LineData(time: .string("2018-12-24"), value: 43.60), + LineData(time: .string("2018-12-26"), value: 45.59), + LineData(time: .string("2018-12-27"), value: 45.53), + LineData(time: .string("2018-12-28"), value: 45.78), + LineData(time: .string("2018-12-31"), value: 46.08), + LineData(time: .string("2019-01-02"), value: 46.94), + LineData(time: .string("2019-01-03"), value: 46.57), + LineData(time: .string("2019-01-04"), value: 47.95), + LineData(time: .string("2019-01-07"), value: 47.64), + LineData(time: .string("2019-01-08"), value: 47.54), + LineData(time: .string("2019-01-09"), value: 47.80), + LineData(time: .string("2019-01-10"), value: 47.75), + LineData(time: .string("2019-01-11"), value: 47.87), + LineData(time: .string("2019-01-14"), value: 48.42), + LineData(time: .string("2019-01-15"), value: 47.67), + LineData(time: .string("2019-01-16"), value: 48.94), + LineData(time: .string("2019-01-17"), value: 49.23), + LineData(time: .string("2019-01-18"), value: 50.01), + LineData(time: .string("2019-01-22"), value: 49.86), + LineData(time: .string("2019-01-23"), value: 50.12), + LineData(time: .string("2019-01-24"), value: 49.98), + LineData(time: .string("2019-01-25"), value: 50.13), + LineData(time: .string("2019-01-28"), value: 49.82), + LineData(time: .string("2019-01-29"), value: 49.85), + LineData(time: .string("2019-01-30"), value: 50.09), + LineData(time: .string("2019-01-31"), value: 48.91), + LineData(time: .string("2019-02-01"), value: 48.91), + LineData(time: .string("2019-02-04"), value: 49.06), + LineData(time: .string("2019-02-05"), value: 49.27), + LineData(time: .string("2019-02-06"), value: 49.22), + LineData(time: .string("2019-02-07"), value: 48.08), + LineData(time: .string("2019-02-08"), value: 47.65), + LineData(time: .string("2019-02-11"), value: 47.65), + LineData(time: .string("2019-02-12"), value: 49.05), + LineData(time: .string("2019-02-13"), value: 49.02), + LineData(time: .string("2019-02-14"), value: 48.52), + LineData(time: .string("2019-02-15"), value: 49.22), + LineData(time: .string("2019-02-19"), value: 49.38), + LineData(time: .string("2019-02-20"), value: 49.81), + LineData(time: .string("2019-02-21"), value: 49.56), + LineData(time: .string("2019-02-22"), value: 49.02), + LineData(time: .string("2019-02-25"), value: 49.66), + LineData(time: .string("2019-02-26"), value: 49.59), + LineData(time: .string("2019-02-27"), value: 49.90), + LineData(time: .string("2019-02-28"), value: 49.89), + LineData(time: .string("2019-03-01"), value: 50.03), + LineData(time: .string("2019-03-04"), value: 50.11), + LineData(time: .string("2019-03-05"), value: 49.89), + LineData(time: .string("2019-03-06"), value: 49.82), + LineData(time: .string("2019-03-07"), value: 49.68), + LineData(time: .string("2019-03-08"), value: 49.80), + LineData(time: .string("2019-03-11"), value: 49.76), + LineData(time: .string("2019-03-12"), value: 49.65), + LineData(time: .string("2019-03-13"), value: 49.92), + LineData(time: .string("2019-03-14"), value: 50.35), + LineData(time: .string("2019-03-15"), value: 50.66), + LineData(time: .string("2019-03-18"), value: 51.73), + LineData(time: .string("2019-03-19"), value: 51.41), + LineData(time: .string("2019-03-20"), value: 50.40), + LineData(time: .string("2019-03-21"), value: 49.86), + LineData(time: .string("2019-03-22"), value: 48.31), + LineData(time: .string("2019-03-25"), value: 48.08), + LineData(time: .string("2019-03-26"), value: 49.01), + LineData(time: .string("2019-03-27"), value: 48.77), + LineData(time: .string("2019-03-28"), value: 49.09), + LineData(time: .string("2019-03-29"), value: 48.32), + LineData(time: .string("2019-04-01"), value: 48.81), + LineData(time: .string("2019-04-02"), value: 48.21), + LineData(time: .string("2019-04-03"), value: 48.86), + LineData(time: .string("2019-04-04"), value: 49.17), + LineData(time: .string("2019-04-05"), value: 48.78), + LineData(time: .string("2019-04-08"), value: 48.88), + LineData(time: .string("2019-04-09"), value: 48.14), + LineData(time: .string("2019-04-10"), value: 47.79), + LineData(time: .string("2019-04-11"), value: 47.74), + LineData(time: .string("2019-04-12"), value: 46.49), + LineData(time: .string("2019-04-15"), value: 46.77), + LineData(time: .string("2019-04-16"), value: 47.65), + LineData(time: .string("2019-04-17"), value: 47.55), + LineData(time: .string("2019-04-18"), value: 47.58), + LineData(time: .string("2019-04-22"), value: 47.26), + LineData(time: .string("2019-04-23"), value: 47.35), + LineData(time: .string("2019-04-24"), value: 47.48), + LineData(time: .string("2019-04-25"), value: 47.51), + LineData(time: .string("2019-04-26"), value: 47.96), + LineData(time: .string("2019-04-29"), value: 48.27), + LineData(time: .string("2019-04-30"), value: 48.41), + LineData(time: .string("2019-05-01"), value: 48.23), + LineData(time: .string("2019-05-02"), value: 48.30), + LineData(time: .string("2019-05-03"), value: 48.65), + LineData(time: .string("2019-05-06"), value: 48.43), + LineData(time: .string("2019-05-07"), value: 47.17), + LineData(time: .string("2019-05-08"), value: 47.00), + LineData(time: .string("2019-05-09"), value: 46.74), + LineData(time: .string("2019-05-10"), value: 47.15), + LineData(time: .string("2019-05-13"), value: 46.33), + LineData(time: .string("2019-05-14"), value: 46.49), + LineData(time: .string("2019-05-15"), value: 45.84), + LineData(time: .string("2019-05-16"), value: 45.90), + LineData(time: .string("2019-05-17"), value: 45.70), + LineData(time: .string("2019-05-20"), value: 45.45), + LineData(time: .string("2019-05-21"), value: 46.33), + LineData(time: .string("2019-05-22"), value: 46.10), + LineData(time: .string("2019-05-23"), value: 45.56), + LineData(time: .string("2019-05-24"), value: 46.17), + LineData(time: .string("2019-05-28"), value: 46.01) + ] + series.setData(data: data) + self.series = series + } + + @objc private func valueChanged(_ sender: UISegmentedControl) { + let locale = locales[sender.selectedSegmentIndex] + let dateFormat = locale == "ja-JP" ? "yyyy-MM-dd" : "dd MMM \'yy" + let localizationOptions = LocalizationOptions(locale: locale, dateFormat: dateFormat) + chart.applyOptions(options: ChartOptions(localization: localizationOptions)) + } + +} diff --git a/ExampleSPM/LightweightCharts/Example/CustomPriceFormatterViewController.swift b/ExampleSPM/LightweightCharts/Example/CustomPriceFormatterViewController.swift new file mode 100644 index 0000000..f961d18 --- /dev/null +++ b/ExampleSPM/LightweightCharts/Example/CustomPriceFormatterViewController.swift @@ -0,0 +1,328 @@ +import UIKit +import LightweightCharts + +class CustomPriceFormatterViewController: UIViewController { + + enum SourceType: CaseIterable { + case js + case native + + var title: String { + switch self { + case .js: + return "JavaScript" + case .native: + return "Swift" + } + } + } + + enum FormatterType: CaseIterable { + case dollar + case pound + + var formatterString: String { + switch self { + case .dollar: return "function(price) { return '$' + price.toFixed(2); }" + case .pound: return "function(price) { return '\u{00A3}' + price.toFixed(2); }" + } + } + + var formatterClosure: (BarPrice) -> String { + switch self { + case .dollar: return { "🦄$\(($0 * 100).rounded() / 100)" } + case .pound: return { "☁️\u{00A3}\(($0 * 100).rounded() / 100)" } + } + } + + var title: String { + switch self { + case .dollar: return "Dollar" + case .pound: return "Pound" + } + } + + } + + private var chart: LightweightCharts! + private var series: AreaSeries! + + private var selectedFormat: FormatterType = .dollar { + didSet { + updateFormatter() + } + } + private var selectedSource: SourceType = .js { + didSet { + updateFormatter() + } + } + + override func viewDidLoad() { + super.viewDidLoad() + if #available(iOS 13.0, *) { + view.backgroundColor = .systemBackground + } else { + view.backgroundColor = .white + } + + setupUI() + setupData() + } + + private func setupUI() { + let sourceSegmentedControl = UISegmentedControl(items: SourceType.allCases.map { $0.title }) + sourceSegmentedControl.addTarget(self, action: #selector(sourceValueChanged), for: .valueChanged) + view.addSubview(sourceSegmentedControl) + sourceSegmentedControl.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + sourceSegmentedControl.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor), + sourceSegmentedControl.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + ]) + } else { + NSLayoutConstraint.activate([ + sourceSegmentedControl.centerXAnchor.constraint(equalTo: view.centerXAnchor), + sourceSegmentedControl.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } + sourceSegmentedControl.selectedSegmentIndex = 0 + + let formatterSegmentedControl = UISegmentedControl(items: FormatterType.allCases.map { $0.title }) + formatterSegmentedControl.addTarget(self, action: #selector(formatterValueChanged), for: .valueChanged) + view.addSubview(formatterSegmentedControl) + formatterSegmentedControl.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + formatterSegmentedControl.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor), + formatterSegmentedControl.bottomAnchor.constraint(equalTo: sourceSegmentedControl.topAnchor, constant: -8) + ]) + } else { + NSLayoutConstraint.activate([ + formatterSegmentedControl.centerXAnchor.constraint(equalTo: view.centerXAnchor), + formatterSegmentedControl.bottomAnchor.constraint(equalTo: sourceSegmentedControl.topAnchor, constant: -8) + ]) + } + formatterSegmentedControl.selectedSegmentIndex = 0 + + + let options = ChartOptions( + layout: LayoutOptions(backgroundColor: "#000", textColor: "rgba(255, 255, 255, 0.8)"), + rightPriceScale: VisiblePriceScaleOptions(borderColor: "rgba(255, 255, 255, 0.8)"), + timeScale: TimeScaleOptions(borderColor: "rgba(255, 255, 255, 0.8)"), + crosshair: CrosshairOptions(mode: .normal), + grid: GridOptions( + verticalLines: GridLineOptions(color: "rgba(255, 255, 255, 0.2)"), + horizontalLines: GridLineOptions(color: "rgba(255, 255, 255, 0.2)") + ), + localization: LocalizationOptions(priceFormatter: .javaScript(FormatterType.allCases[0].formatterString)) + ) + let chart = LightweightCharts(options: options) + view.addSubview(chart) + chart.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + chart.bottomAnchor.constraint(equalTo: formatterSegmentedControl.topAnchor, constant: -8) + ]) + } else { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.topAnchor), + chart.bottomAnchor.constraint(equalTo: formatterSegmentedControl.topAnchor, constant: -8) + ]) + } + self.chart = chart + } + + private func setupData() { + let options = AreaSeriesOptions( + topColor: "rgba(21, 101, 192, 0.5)", + bottomColor: "rgba(21, 101, 192, 0.5)", + lineColor: "rgba(255, 255, 255, 0.8)", + lineWidth: .two, + crosshairMarkerBorderColor: "rgba(255, 255, 255, 1)", + crosshairMarkerBackgroundColor: "rgba(100, 50, 20, 1)" + ) + let series = chart.addAreaSeries(options: options) + let data = [ + LineData(time: .string("2018-10-19"), value: 72.35), + LineData(time: .string("2018-10-22"), value: 72.57), + LineData(time: .string("2018-10-23"), value: 72.10), + LineData(time: .string("2018-10-24"), value: 70.54), + LineData(time: .string("2018-10-25"), value: 69.96), + LineData(time: .string("2018-10-26"), value: 70.40), + LineData(time: .string("2018-10-29"), value: 71.45), + LineData(time: .string("2018-10-30"), value: 72.87), + LineData(time: .string("2018-10-31"), value: 73.61), + LineData(time: .string("2018-11-01"), value: 73.12), + LineData(time: .string("2018-11-02"), value: 72.27), + LineData(time: .string("2018-11-05"), value: 73.12), + LineData(time: .string("2018-11-06"), value: 73.31), + LineData(time: .string("2018-11-07"), value: 75.08), + LineData(time: .string("2018-11-08"), value: 75.48), + LineData(time: .string("2018-11-09"), value: 74.86), + LineData(time: .string("2018-11-12"), value: 74.69), + LineData(time: .string("2018-11-13"), value: 74.61), + LineData(time: .string("2018-11-14"), value: 74.09), + LineData(time: .string("2018-11-15"), value: 74.84), + LineData(time: .string("2018-11-16"), value: 76.06), + LineData(time: .string("2018-11-19"), value: 76.35), + LineData(time: .string("2018-11-20"), value: 74.78), + LineData(time: .string("2018-11-21"), value: 74.79), + LineData(time: .string("2018-11-23"), value: 74.67), + LineData(time: .string("2018-11-26"), value: 75.44), + LineData(time: .string("2018-11-27"), value: 76.34), + LineData(time: .string("2018-11-28"), value: 77.23), + LineData(time: .string("2018-11-29"), value: 77.91), + LineData(time: .string("2018-11-30"), value: 79.34), + LineData(time: .string("2018-12-03"), value: 79.22), + LineData(time: .string("2018-12-04"), value: 78.21), + LineData(time: .string("2018-12-06"), value: 78.37), + LineData(time: .string("2018-12-07"), value: 76.72), + LineData(time: .string("2018-12-10"), value: 77.42), + LineData(time: .string("2018-12-11"), value: 77.11), + LineData(time: .string("2018-12-12"), value: 78.01), + LineData(time: .string("2018-12-13"), value: 79.01), + LineData(time: .string("2018-12-14"), value: 76.48), + LineData(time: .string("2018-12-17"), value: 75.23), + LineData(time: .string("2018-12-18"), value: 74.33), + LineData(time: .string("2018-12-19"), value: 73.77), + LineData(time: .string("2018-12-20"), value: 73.49), + LineData(time: .string("2018-12-21"), value: 72.90), + LineData(time: .string("2018-12-24"), value: 71.15), + LineData(time: .string("2018-12-26"), value: 74.00), + LineData(time: .string("2018-12-27"), value: 75.38), + LineData(time: .string("2018-12-28"), value: 75.37), + LineData(time: .string("2018-12-31"), value: 76.41), + LineData(time: .string("2019-01-02"), value: 75.59), + LineData(time: .string("2019-01-03"), value: 74.04), + LineData(time: .string("2019-01-04"), value: 76.27), + LineData(time: .string("2019-01-07"), value: 75.43), + LineData(time: .string("2019-01-08"), value: 75.99), + LineData(time: .string("2019-01-09"), value: 75.41), + LineData(time: .string("2019-01-10"), value: 74.48), + LineData(time: .string("2019-01-11"), value: 74.90), + LineData(time: .string("2019-01-14"), value: 73.37), + LineData(time: .string("2019-01-15"), value: 74.50), + LineData(time: .string("2019-01-16"), value: 74.61), + LineData(time: .string("2019-01-17"), value: 75.60), + LineData(time: .string("2019-01-18"), value: 75.87), + LineData(time: .string("2019-01-22"), value: 75.83), + LineData(time: .string("2019-01-23"), value: 75.44), + LineData(time: .string("2019-01-24"), value: 73.17), + LineData(time: .string("2019-01-25"), value: 72.95), + LineData(time: .string("2019-01-28"), value: 72.92), + LineData(time: .string("2019-01-29"), value: 73.23), + LineData(time: .string("2019-01-30"), value: 73.37), + LineData(time: .string("2019-01-31"), value: 74.43), + LineData(time: .string("2019-02-01"), value: 76.45), + LineData(time: .string("2019-02-04"), value: 76.87), + LineData(time: .string("2019-02-05"), value: 77.15), + LineData(time: .string("2019-02-06"), value: 77.39), + LineData(time: .string("2019-02-07"), value: 76.82), + LineData(time: .string("2019-02-08"), value: 77.52), + LineData(time: .string("2019-02-11"), value: 76.71), + LineData(time: .string("2019-02-12"), value: 78.52), + LineData(time: .string("2019-02-13"), value: 79.02), + LineData(time: .string("2019-02-14"), value: 78.94), + LineData(time: .string("2019-02-15"), value: 79.81), + LineData(time: .string("2019-02-19"), value: 79.24), + LineData(time: .string("2019-02-20"), value: 79.43), + LineData(time: .string("2019-02-21"), value: 79.83), + LineData(time: .string("2019-02-22"), value: 80.77), + LineData(time: .string("2019-02-25"), value: 80.38), + LineData(time: .string("2019-02-26"), value: 80.74), + LineData(time: .string("2019-02-27"), value: 80.62), + LineData(time: .string("2019-02-28"), value: 81.29), + LineData(time: .string("2019-03-01"), value: 81.65), + LineData(time: .string("2019-03-04"), value: 81.37), + LineData(time: .string("2019-03-05"), value: 81.70), + LineData(time: .string("2019-03-06"), value: 80.76), + LineData(time: .string("2019-03-07"), value: 80.45), + LineData(time: .string("2019-03-08"), value: 79.80), + LineData(time: .string("2019-03-11"), value: 80.87), + LineData(time: .string("2019-03-12"), value: 81.23), + LineData(time: .string("2019-03-13"), value: 81.60), + LineData(time: .string("2019-03-14"), value: 81.49), + LineData(time: .string("2019-03-15"), value: 81.57), + LineData(time: .string("2019-03-18"), value: 81.35), + LineData(time: .string("2019-03-19"), value: 81.91), + LineData(time: .string("2019-03-20"), value: 82.08), + LineData(time: .string("2019-03-21"), value: 82.95), + LineData(time: .string("2019-03-22"), value: 82.29), + LineData(time: .string("2019-03-25"), value: 82.35), + LineData(time: .string("2019-03-26"), value: 82.92), + LineData(time: .string("2019-03-27"), value: 82.29), + LineData(time: .string("2019-03-28"), value: 82.63), + LineData(time: .string("2019-03-29"), value: 83.17), + LineData(time: .string("2019-04-01"), value: 83.30), + LineData(time: .string("2019-04-02"), value: 83.21), + LineData(time: .string("2019-04-03"), value: 83.18), + LineData(time: .string("2019-04-04"), value: 81.85), + LineData(time: .string("2019-04-05"), value: 81.15), + LineData(time: .string("2019-04-08"), value: 80.95), + LineData(time: .string("2019-04-09"), value: 80.80), + LineData(time: .string("2019-04-10"), value: 80.82), + LineData(time: .string("2019-04-11"), value: 79.84), + LineData(time: .string("2019-04-12"), value: 79.43), + LineData(time: .string("2019-04-15"), value: 78.53), + LineData(time: .string("2019-04-16"), value: 77.56), + LineData(time: .string("2019-04-17"), value: 73.92), + LineData(time: .string("2019-04-18"), value: 73.19), + LineData(time: .string("2019-04-22"), value: 73.46), + LineData(time: .string("2019-04-23"), value: 74.60), + LineData(time: .string("2019-04-24"), value: 74.73), + LineData(time: .string("2019-04-25"), value: 76.34), + LineData(time: .string("2019-04-26"), value: 76.63), + LineData(time: .string("2019-04-29"), value: 76.78), + LineData(time: .string("2019-04-30"), value: 78.71), + LineData(time: .string("2019-05-01"), value: 78.72), + LineData(time: .string("2019-05-02"), value: 79.52), + LineData(time: .string("2019-05-03"), value: 80.00), + LineData(time: .string("2019-05-06"), value: 79.48), + LineData(time: .string("2019-05-07"), value: 77.90), + LineData(time: .string("2019-05-08"), value: 78.18), + LineData(time: .string("2019-05-09"), value: 78.33), + LineData(time: .string("2019-05-10"), value: 78.19), + LineData(time: .string("2019-05-13"), value: 77.17), + LineData(time: .string("2019-05-14"), value: 77.42), + LineData(time: .string("2019-05-15"), value: 77.55), + LineData(time: .string("2019-05-16"), value: 79.13), + LineData(time: .string("2019-05-17"), value: 78.72), + LineData(time: .string("2019-05-20"), value: 78.88), + LineData(time: .string("2019-05-21"), value: 79.50), + LineData(time: .string("2019-05-22"), value: 80.98), + LineData(time: .string("2019-05-23"), value: 81.02), + LineData(time: .string("2019-05-24"), value: 81.17), + LineData(time: .string("2019-05-28"), value: 81.10) + ] + series.setData(data: data) + self.series = series + } + + private func updateFormatter() { + let method: JavaScriptMethod + switch selectedSource { + case .js: + method = .javaScript(selectedFormat.formatterString) + case .native: + method = .closure(selectedFormat.formatterClosure) + } + + let options = ChartOptions(localization: LocalizationOptions(priceFormatter: method)) + chart.applyOptions(options: options) + } + + @objc private func formatterValueChanged(_ sender: UISegmentedControl) { + selectedFormat = FormatterType.allCases[sender.selectedSegmentIndex] + } + + @objc private func sourceValueChanged(_ sender: UISegmentedControl) { + selectedSource = SourceType.allCases[sender.selectedSegmentIndex] + } + +} diff --git a/ExampleSPM/LightweightCharts/Example/CustomThemesViewController.swift b/ExampleSPM/LightweightCharts/Example/CustomThemesViewController.swift new file mode 100644 index 0000000..b9143f2 --- /dev/null +++ b/ExampleSPM/LightweightCharts/Example/CustomThemesViewController.swift @@ -0,0 +1,301 @@ +import UIKit +import LightweightCharts + +class CustomThemesViewController: UIViewController { + + enum Theme: CaseIterable { + case dark + case light + + var title: String { + switch self { + case .dark: return "Dark" + case .light: return "Light" + } + } + + var chartOptions: ChartOptions { + switch self { + case .dark: + return ChartOptions( + watermark: WatermarkOptions(color: "rgba(0, 0, 0, 0)"), + // TODO: need lineColor + layout: LayoutOptions(backgroundColor: "#2B2B43", textColor: "#D9D9D9"), + crosshair: CrosshairOptions( + vertLine: CrosshairLineOptions(color: "#758696"), + horzLine: CrosshairLineOptions(color: "#758696") + ), + grid: GridOptions( + verticalLines: GridLineOptions(color: "#2B2B43"), + horizontalLines: GridLineOptions(color: "#363C4E") + ) + ) + case .light: + return ChartOptions( + watermark: WatermarkOptions(color: "rgba(0, 0, 0, 0)"), + // TODO: need lineColor + layout: LayoutOptions(backgroundColor: "#FFFFFF", textColor: "#191919"), + crosshair: CrosshairOptions( + vertLine: CrosshairLineOptions(color: "#758696"), + horzLine: CrosshairLineOptions(color: "#758696") + ), + grid: GridOptions( + verticalLines: GridLineOptions(visible: false), + horizontalLines: GridLineOptions(color: "#f0f3fa") + ) + ) + } + } + + var seriesOptions: AreaSeriesOptions { + switch self { + case .dark: + return AreaSeriesOptions( + topColor: "rgba(32, 226, 47, 0.56)", + bottomColor: "rgba(32, 226, 47, 0.04)", + lineColor: "rgba(32, 226, 47, 1)" + ) + case .light: + return AreaSeriesOptions( + topColor: "rgba(33, 150, 243, 0.56)", + bottomColor: "rgba(33, 150, 243, 0.04)", + lineColor: "rgba(33, 150, 243, 1)" + ) + } + } + } + + private var chart: LightweightCharts! + private var series: AreaSeries! + + override func viewDidLoad() { + super.viewDidLoad() + if #available(iOS 13.0, *) { + view.backgroundColor = .systemBackground + } else { + view.backgroundColor = .white + } + + setupUI() + setupData() + syncToTheme(.dark) + } + + private func setupUI() { + let segmentedControl = UISegmentedControl(items: Theme.allCases.map { $0.title }) + segmentedControl.addTarget(self, action: #selector(valueChanged), for: .valueChanged) + view.addSubview(segmentedControl) + segmentedControl.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + segmentedControl.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor), + segmentedControl.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + ]) + } else { + NSLayoutConstraint.activate([ + segmentedControl.centerXAnchor.constraint(equalTo: view.centerXAnchor), + segmentedControl.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } + + let options = ChartOptions( + rightPriceScale: VisiblePriceScaleOptions(borderVisible: false), + timeScale: TimeScaleOptions(borderVisible: false) + ) + let chart = LightweightCharts(options: options) + view.addSubview(chart) + chart.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + chart.bottomAnchor.constraint(equalTo: segmentedControl.topAnchor, constant: -16) + ]) + } else { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.topAnchor), + chart.bottomAnchor.constraint(equalTo: segmentedControl.topAnchor, constant: -16) + ]) + } + self.chart = chart + + segmentedControl.selectedSegmentIndex = 0 + } + + private func setupData() { + let options = AreaSeriesOptions( + topColor: "rgba(33, 150, 243, 0.56)", + bottomColor: "rgba(33, 150, 243, 0.04)", + lineColor: "rgba(33, 150, 243, 1)", + lineWidth: .two + ) + let series = chart.addAreaSeries(options: options) + let data = [ + LineData(time: .string("2018-10-19"), value: 35.98), + LineData(time: .string("2018-10-22"), value: 35.75), + LineData(time: .string("2018-10-23"), value: 35.65), + LineData(time: .string("2018-10-24"), value: 34.12), + LineData(time: .string("2018-10-25"), value: 35.84), + LineData(time: .string("2018-10-26"), value: 35.24), + LineData(time: .string("2018-10-29"), value: 35.99), + LineData(time: .string("2018-10-30"), value: 37.71), + LineData(time: .string("2018-10-31"), value: 38.14), + LineData(time: .string("2018-11-01"), value: 37.95), + LineData(time: .string("2018-11-02"), value: 37.66), + LineData(time: .string("2018-11-05"), value: 38.02), + LineData(time: .string("2018-11-06"), value: 37.73), + LineData(time: .string("2018-11-07"), value: 38.30), + LineData(time: .string("2018-11-08"), value: 38.30), + LineData(time: .string("2018-11-09"), value: 38.34), + LineData(time: .string("2018-11-12"), value: 38.00), + LineData(time: .string("2018-11-13"), value: 37.72), + LineData(time: .string("2018-11-14"), value: 38.29), + LineData(time: .string("2018-11-15"), value: 38.49), + LineData(time: .string("2018-11-16"), value: 38.59), + LineData(time: .string("2018-11-19"), value: 38.18), + LineData(time: .string("2018-11-20"), value: 36.76), + LineData(time: .string("2018-11-21"), value: 37.51), + LineData(time: .string("2018-11-23"), value: 37.39), + LineData(time: .string("2018-11-26"), value: 37.77), + LineData(time: .string("2018-11-27"), value: 38.36), + LineData(time: .string("2018-11-28"), value: 39.06), + LineData(time: .string("2018-11-29"), value: 39.42), + LineData(time: .string("2018-11-30"), value: 39.01), + LineData(time: .string("2018-12-03"), value: 39.15), + LineData(time: .string("2018-12-04"), value: 37.69), + LineData(time: .string("2018-12-06"), value: 37.88), + LineData(time: .string("2018-12-07"), value: 37.41), + LineData(time: .string("2018-12-10"), value: 37.35), + LineData(time: .string("2018-12-11"), value: 36.84), + LineData(time: .string("2018-12-12"), value: 36.98), + LineData(time: .string("2018-12-13"), value: 36.76), + LineData(time: .string("2018-12-14"), value: 36.34), + LineData(time: .string("2018-12-17"), value: 36.21), + LineData(time: .string("2018-12-18"), value: 35.65), + LineData(time: .string("2018-12-19"), value: 35.19), + LineData(time: .string("2018-12-20"), value: 34.62), + LineData(time: .string("2018-12-21"), value: 33.75), + LineData(time: .string("2018-12-24"), value: 33.07), + LineData(time: .string("2018-12-26"), value: 34.14), + LineData(time: .string("2018-12-27"), value: 34.47), + LineData(time: .string("2018-12-28"), value: 34.35), + LineData(time: .string("2018-12-31"), value: 34.05), + LineData(time: .string("2019-01-02"), value: 34.37), + LineData(time: .string("2019-01-03"), value: 34.64), + LineData(time: .string("2019-01-04"), value: 35.81), + LineData(time: .string("2019-01-07"), value: 35.43), + LineData(time: .string("2019-01-08"), value: 35.72), + LineData(time: .string("2019-01-09"), value: 36.06), + LineData(time: .string("2019-01-10"), value: 35.82), + LineData(time: .string("2019-01-11"), value: 35.63), + LineData(time: .string("2019-01-14"), value: 35.77), + LineData(time: .string("2019-01-15"), value: 35.83), + LineData(time: .string("2019-01-16"), value: 35.90), + LineData(time: .string("2019-01-17"), value: 35.91), + LineData(time: .string("2019-01-18"), value: 36.21), + LineData(time: .string("2019-01-22"), value: 34.97), + LineData(time: .string("2019-01-23"), value: 36.89), + LineData(time: .string("2019-01-24"), value: 36.24), + LineData(time: .string("2019-01-25"), value: 35.78), + LineData(time: .string("2019-01-28"), value: 35.37), + LineData(time: .string("2019-01-29"), value: 36.08), + LineData(time: .string("2019-01-30"), value: 35.43), + LineData(time: .string("2019-01-31"), value: 36.57), + LineData(time: .string("2019-02-01"), value: 36.79), + LineData(time: .string("2019-02-04"), value: 36.77), + LineData(time: .string("2019-02-05"), value: 37.15), + LineData(time: .string("2019-02-06"), value: 37.17), + LineData(time: .string("2019-02-07"), value: 37.68), + LineData(time: .string("2019-02-08"), value: 37.60), + LineData(time: .string("2019-02-11"), value: 37.00), + LineData(time: .string("2019-02-12"), value: 37.24), + LineData(time: .string("2019-02-13"), value: 37.03), + LineData(time: .string("2019-02-14"), value: 37.26), + LineData(time: .string("2019-02-15"), value: 37.77), + LineData(time: .string("2019-02-19"), value: 37.55), + LineData(time: .string("2019-02-20"), value: 37.79), + LineData(time: .string("2019-02-21"), value: 38.47), + LineData(time: .string("2019-02-22"), value: 38.61), + LineData(time: .string("2019-02-25"), value: 38.57), + LineData(time: .string("2019-02-26"), value: 38.80), + LineData(time: .string("2019-02-27"), value: 38.53), + LineData(time: .string("2019-02-28"), value: 38.67), + LineData(time: .string("2019-03-01"), value: 39.10), + LineData(time: .string("2019-03-04"), value: 38.73), + LineData(time: .string("2019-03-05"), value: 38.72), + LineData(time: .string("2019-03-06"), value: 38.61), + LineData(time: .string("2019-03-07"), value: 38.38), + LineData(time: .string("2019-03-08"), value: 38.19), + LineData(time: .string("2019-03-11"), value: 39.17), + LineData(time: .string("2019-03-12"), value: 39.49), + LineData(time: .string("2019-03-13"), value: 39.56), + LineData(time: .string("2019-03-14"), value: 39.87), + LineData(time: .string("2019-03-15"), value: 40.47), + LineData(time: .string("2019-03-18"), value: 39.92), + LineData(time: .string("2019-03-19"), value: 39.78), + LineData(time: .string("2019-03-20"), value: 39.47), + LineData(time: .string("2019-03-21"), value: 40.05), + LineData(time: .string("2019-03-22"), value: 39.46), + LineData(time: .string("2019-03-25"), value: 39.18), + LineData(time: .string("2019-03-26"), value: 39.63), + LineData(time: .string("2019-03-27"), value: 40.21), + LineData(time: .string("2019-03-28"), value: 40.42), + LineData(time: .string("2019-03-29"), value: 39.98), + LineData(time: .string("2019-04-01"), value: 40.31), + LineData(time: .string("2019-04-02"), value: 40.02), + LineData(time: .string("2019-04-03"), value: 40.27), + LineData(time: .string("2019-04-04"), value: 40.41), + LineData(time: .string("2019-04-05"), value: 40.42), + LineData(time: .string("2019-04-08"), value: 40.71), + LineData(time: .string("2019-04-09"), value: 41.04), + LineData(time: .string("2019-04-10"), value: 41.08), + LineData(time: .string("2019-04-11"), value: 41.04), + LineData(time: .string("2019-04-12"), value: 41.30), + LineData(time: .string("2019-04-15"), value: 41.78), + LineData(time: .string("2019-04-16"), value: 41.97), + LineData(time: .string("2019-04-17"), value: 42.57), + LineData(time: .string("2019-04-18"), value: 42.43), + LineData(time: .string("2019-04-22"), value: 42.00), + LineData(time: .string("2019-04-23"), value: 41.99), + LineData(time: .string("2019-04-24"), value: 41.85), + LineData(time: .string("2019-04-25"), value: 42.93), + LineData(time: .string("2019-04-26"), value: 43.08), + LineData(time: .string("2019-04-29"), value: 43.45), + LineData(time: .string("2019-04-30"), value: 43.53), + LineData(time: .string("2019-05-01"), value: 43.42), + LineData(time: .string("2019-05-02"), value: 42.65), + LineData(time: .string("2019-05-03"), value: 43.29), + LineData(time: .string("2019-05-06"), value: 43.30), + LineData(time: .string("2019-05-07"), value: 42.76), + LineData(time: .string("2019-05-08"), value: 42.55), + LineData(time: .string("2019-05-09"), value: 42.92), + LineData(time: .string("2019-05-10"), value: 43.15), + LineData(time: .string("2019-05-13"), value: 42.28), + LineData(time: .string("2019-05-14"), value: 42.91), + LineData(time: .string("2019-05-15"), value: 42.49), + LineData(time: .string("2019-05-16"), value: 43.19), + LineData(time: .string("2019-05-17"), value: 43.54), + LineData(time: .string("2019-05-20"), value: 42.78), + LineData(time: .string("2019-05-21"), value: 43.29), + LineData(time: .string("2019-05-22"), value: 43.30), + LineData(time: .string("2019-05-23"), value: 42.73), + LineData(time: .string("2019-05-24"), value: 42.67), + LineData(time: .string("2019-05-28"), value: 42.75) + ] + series.setData(data: data) + self.series = series + } + + private func syncToTheme(_ theme: Theme) { + chart.applyOptions(options: theme.chartOptions) + series.applyOptions(options: theme.seriesOptions) + } + + @objc private func valueChanged(_ sender: UISegmentedControl) { + syncToTheme(Theme.allCases[sender.selectedSegmentIndex]) + } + +} diff --git a/ExampleSPM/LightweightCharts/Example/CustomWatermarkViewController.swift b/ExampleSPM/LightweightCharts/Example/CustomWatermarkViewController.swift new file mode 100644 index 0000000..aadb14e --- /dev/null +++ b/ExampleSPM/LightweightCharts/Example/CustomWatermarkViewController.swift @@ -0,0 +1,223 @@ +import UIKit +import LightweightCharts + +class CustomWatermarkViewController: UIViewController { + + private var chart: LightweightCharts! + private var series: AreaSeries! + + override func viewDidLoad() { + super.viewDidLoad() + if #available(iOS 13.0, *) { + view.backgroundColor = .systemBackground + } else { + view.backgroundColor = .white + } + + setupUI() + setupData() + } + + private func setupUI() { + let options = ChartOptions( + watermark: WatermarkOptions( + color: "rgba(171, 71, 188, 0.5)", + visible: true, + text: "Watermark Example", + fontSize: 24, + horizontalAlignment: .center, + verticalAlignment: .center + ), + layout: LayoutOptions(backgroundColor: "#ffffff", textColor: "#333"), + rightPriceScale: VisiblePriceScaleOptions(scaleMargins: PriceScaleMargins(top: 0.1, bottom: 0.2)), + grid: GridOptions( + verticalLines: GridLineOptions(color: "#eee"), + horizontalLines: GridLineOptions(color: "#ffffff") + ) + ) + let chart = LightweightCharts(options: options) + view.addSubview(chart) + chart.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + ]) + } else { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } + self.chart = chart + } + + private func setupData() { + let options = AreaSeriesOptions( + topColor: "rgba(171, 71, 188, 0.56)", + bottomColor: "rgba(171, 71, 188, 0.04)", + lineColor: "rgba(171, 71, 188, 1)", + lineWidth: .two + ) + let series = chart.addAreaSeries(options: options) + let data = [ + LineData(time: .string("2018-10-19"), value: 75.46), + LineData(time: .string("2018-10-22"), value: 76.69), + LineData(time: .string("2018-10-23"), value: 73.82), + LineData(time: .string("2018-10-24"), value: 71.50), + LineData(time: .string("2018-10-25"), value: 72.74), + LineData(time: .string("2018-10-26"), value: 72.06), + LineData(time: .string("2018-10-29"), value: 70.56), + LineData(time: .string("2018-10-30"), value: 73.47), + LineData(time: .string("2018-10-31"), value: 72.64), + LineData(time: .string("2018-11-01"), value: 74.28), + LineData(time: .string("2018-11-02"), value: 72.86), + LineData(time: .string("2018-11-05"), value: 74.59), + LineData(time: .string("2018-11-06"), value: 75.48), + LineData(time: .string("2018-11-07"), value: 76.82), + LineData(time: .string("2018-11-08"), value: 75.57), + LineData(time: .string("2018-11-09"), value: 74.25), + LineData(time: .string("2018-11-12"), value: 74.42), + LineData(time: .string("2018-11-13"), value: 72.43), + LineData(time: .string("2018-11-14"), value: 72.51), + LineData(time: .string("2018-11-15"), value: 73.06), + LineData(time: .string("2018-11-16"), value: 73.40), + LineData(time: .string("2018-11-19"), value: 71.23), + LineData(time: .string("2018-11-20"), value: 68.18), + LineData(time: .string("2018-11-21"), value: 69.49), + LineData(time: .string("2018-11-23"), value: 67.31), + LineData(time: .string("2018-11-26"), value: 68.43), + LineData(time: .string("2018-11-27"), value: 68.09), + LineData(time: .string("2018-11-28"), value: 69.30), + LineData(time: .string("2018-11-29"), value: 69.91), + LineData(time: .string("2018-11-30"), value: 69.50), + LineData(time: .string("2018-12-03"), value: 72.42), + LineData(time: .string("2018-12-04"), value: 70.78), + LineData(time: .string("2018-12-06"), value: 69.01), + LineData(time: .string("2018-12-07"), value: 68.57), + LineData(time: .string("2018-12-10"), value: 67.67), + LineData(time: .string("2018-12-11"), value: 68.01), + LineData(time: .string("2018-12-12"), value: 68.79), + LineData(time: .string("2018-12-13"), value: 69.75), + LineData(time: .string("2018-12-14"), value: 68.20), + LineData(time: .string("2018-12-17"), value: 67.02), + LineData(time: .string("2018-12-18"), value: 64.75), + LineData(time: .string("2018-12-19"), value: 63.09), + LineData(time: .string("2018-12-20"), value: 62.19), + LineData(time: .string("2018-12-21"), value: 61.42), + LineData(time: .string("2018-12-24"), value: 60.07), + LineData(time: .string("2018-12-26"), value: 62.54), + LineData(time: .string("2018-12-27"), value: 61.67), + LineData(time: .string("2018-12-28"), value: 60.98), + LineData(time: .string("2018-12-31"), value: 61.55), + LineData(time: .string("2019-01-02"), value: 60.91), + LineData(time: .string("2019-01-03"), value: 61.15), + LineData(time: .string("2019-01-04"), value: 62.81), + LineData(time: .string("2019-01-07"), value: 62.55), + LineData(time: .string("2019-01-08"), value: 63.89), + LineData(time: .string("2019-01-09"), value: 65.45), + LineData(time: .string("2019-01-10"), value: 64.86), + LineData(time: .string("2019-01-11"), value: 63.47), + LineData(time: .string("2019-01-14"), value: 62.45), + LineData(time: .string("2019-01-15"), value: 63.45), + LineData(time: .string("2019-01-16"), value: 63.73), + LineData(time: .string("2019-01-17"), value: 63.96), + LineData(time: .string("2019-01-18"), value: 64.93), + LineData(time: .string("2019-01-22"), value: 61.83), + LineData(time: .string("2019-01-23"), value: 61.94), + LineData(time: .string("2019-01-24"), value: 63.22), + LineData(time: .string("2019-01-25"), value: 64.07), + LineData(time: .string("2019-01-28"), value: 63.20), + LineData(time: .string("2019-01-29"), value: 63.57), + LineData(time: .string("2019-01-30"), value: 64.28), + LineData(time: .string("2019-01-31"), value: 64.27), + LineData(time: .string("2019-02-01"), value: 64.63), + LineData(time: .string("2019-02-04"), value: 64.37), + LineData(time: .string("2019-02-05"), value: 64.57), + LineData(time: .string("2019-02-06"), value: 63.70), + LineData(time: .string("2019-02-07"), value: 63.41), + LineData(time: .string("2019-02-08"), value: 63.37), + LineData(time: .string("2019-02-11"), value: 62.32), + LineData(time: .string("2019-02-12"), value: 62.89), + LineData(time: .string("2019-02-13"), value: 63.72), + LineData(time: .string("2019-02-14"), value: 63.89), + LineData(time: .string("2019-02-15"), value: 64.48), + LineData(time: .string("2019-02-19"), value: 66.38), + LineData(time: .string("2019-02-20"), value: 67.38), + LineData(time: .string("2019-02-21"), value: 66.48), + LineData(time: .string("2019-02-22"), value: 67.54), + LineData(time: .string("2019-02-25"), value: 66.80), + LineData(time: .string("2019-02-26"), value: 67.26), + LineData(time: .string("2019-02-27"), value: 67.25), + LineData(time: .string("2019-02-28"), value: 65.86), + LineData(time: .string("2019-03-01"), value: 65.92), + LineData(time: .string("2019-03-04"), value: 66.04), + LineData(time: .string("2019-03-05"), value: 66.36), + LineData(time: .string("2019-03-06"), value: 65.68), + LineData(time: .string("2019-03-07"), value: 64.41), + LineData(time: .string("2019-03-08"), value: 63.72), + LineData(time: .string("2019-03-11"), value: 64.85), + LineData(time: .string("2019-03-12"), value: 64.96), + LineData(time: .string("2019-03-13"), value: 65.25), + LineData(time: .string("2019-03-14"), value: 64.90), + LineData(time: .string("2019-03-15"), value: 65.12), + LineData(time: .string("2019-03-18"), value: 66.70), + LineData(time: .string("2019-03-19"), value: 67.71), + LineData(time: .string("2019-03-20"), value: 68.60), + LineData(time: .string("2019-03-21"), value: 68.41), + LineData(time: .string("2019-03-22"), value: 66.03), + LineData(time: .string("2019-03-25"), value: 65.06), + LineData(time: .string("2019-03-26"), value: 65.31), + LineData(time: .string("2019-03-27"), value: 64.93), + LineData(time: .string("2019-03-28"), value: 65.49), + LineData(time: .string("2019-03-29"), value: 65.43), + LineData(time: .string("2019-04-01"), value: 66.66), + LineData(time: .string("2019-04-02"), value: 65.92), + LineData(time: .string("2019-04-03"), value: 65.89), + LineData(time: .string("2019-04-04"), value: 66.64), + LineData(time: .string("2019-04-05"), value: 67.28), + LineData(time: .string("2019-04-08"), value: 67.58), + LineData(time: .string("2019-04-09"), value: 67.29), + LineData(time: .string("2019-04-10"), value: 67.04), + LineData(time: .string("2019-04-11"), value: 65.80), + LineData(time: .string("2019-04-12"), value: 65.70), + LineData(time: .string("2019-04-15"), value: 64.53), + LineData(time: .string("2019-04-16"), value: 64.51), + LineData(time: .string("2019-04-17"), value: 64.01), + LineData(time: .string("2019-04-18"), value: 64.59), + LineData(time: .string("2019-04-22"), value: 65.41), + LineData(time: .string("2019-04-23"), value: 65.25), + LineData(time: .string("2019-04-24"), value: 64.45), + LineData(time: .string("2019-04-25"), value: 64.04), + LineData(time: .string("2019-04-26"), value: 63.59), + LineData(time: .string("2019-04-29"), value: 63.67), + LineData(time: .string("2019-04-30"), value: 63.29), + LineData(time: .string("2019-05-01"), value: 62.94), + LineData(time: .string("2019-05-02"), value: 61.85), + LineData(time: .string("2019-05-03"), value: 62.42), + LineData(time: .string("2019-05-06"), value: 61.93), + LineData(time: .string("2019-05-07"), value: 60.05), + LineData(time: .string("2019-05-08"), value: 60.02), + LineData(time: .string("2019-05-09"), value: 59.34), + LineData(time: .string("2019-05-10"), value: 58.94), + LineData(time: .string("2019-05-13"), value: 57.87), + LineData(time: .string("2019-05-14"), value: 59.11), + LineData(time: .string("2019-05-15"), value: 58.41), + LineData(time: .string("2019-05-16"), value: 58.90), + LineData(time: .string("2019-05-17"), value: 58.07), + LineData(time: .string("2019-05-20"), value: 58.10), + LineData(time: .string("2019-05-21"), value: 58.38), + LineData(time: .string("2019-05-22"), value: 57.85), + LineData(time: .string("2019-05-23"), value: 56.31), + LineData(time: .string("2019-05-24"), value: 57.36), + LineData(time: .string("2019-05-28"), value: 57.19) + ] + series.setData(data: data) + self.series = series + } + +} diff --git a/ExampleSPM/LightweightCharts/Example/FitContentViewController.swift b/ExampleSPM/LightweightCharts/Example/FitContentViewController.swift new file mode 100644 index 0000000..53ebb55 --- /dev/null +++ b/ExampleSPM/LightweightCharts/Example/FitContentViewController.swift @@ -0,0 +1,413 @@ +import UIKit +import LightweightCharts + +class FitContentViewController: UIViewController { + + private var chart: LightweightCharts! + private var series: AreaSeries! + + override func viewDidLoad() { + super.viewDidLoad() + if #available(iOS 13.0, *) { + view.backgroundColor = .systemBackground + } else { + view.backgroundColor = .white + } + + setupUI() + setupData() + chart.timeScale().fitContent() + } + + private func setupUI() { + let options = ChartOptions( + rightPriceScale: VisiblePriceScaleOptions( + scaleMargins: PriceScaleMargins(top: 0.1, bottom: 0.1) + ) + ) + let chart = LightweightCharts(options: options) + view.addSubview(chart) + chart.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + ]) + } else { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } + self.chart = chart + } + + private func setupData() { + let options = AreaSeriesOptions( + topColor: "rgba(76, 175, 80, 0.56)", + bottomColor: "rgba(76, 175, 80, 0.04)", + lineColor: "rgba(76, 175, 80, 1)", + lineWidth: .two + ) + let series = chart.addAreaSeries(options: options) + let data = [ + LineData(time: .string("2018-01-04"), value: 173.03), + LineData(time: .string("2018-01-05"), value: 175.00), + LineData(time: .string("2018-01-08"), value: 174.35), + LineData(time: .string("2018-01-09"), value: 174.33), + LineData(time: .string("2018-01-10"), value: 174.29), + LineData(time: .string("2018-01-11"), value: 175.28), + LineData(time: .string("2018-01-12"), value: 177.09), + LineData(time: .string("2018-01-16"), value: 176.19), + LineData(time: .string("2018-01-17"), value: 179.10), + LineData(time: .string("2018-01-18"), value: 179.26), + LineData(time: .string("2018-01-19"), value: 178.46), + LineData(time: .string("2018-01-22"), value: 177.00), + LineData(time: .string("2018-01-23"), value: 177.04), + LineData(time: .string("2018-01-24"), value: 174.22), + LineData(time: .string("2018-01-25"), value: 171.11), + LineData(time: .string("2018-01-26"), value: 171.51), + LineData(time: .string("2018-01-29"), value: 167.96), + LineData(time: .string("2018-01-30"), value: 166.97), + LineData(time: .string("2018-01-31"), value: 167.43), + LineData(time: .string("2018-02-01"), value: 167.78), + LineData(time: .string("2018-02-02"), value: 160.50), + LineData(time: .string("2018-02-05"), value: 156.49), + LineData(time: .string("2018-02-06"), value: 163.03), + LineData(time: .string("2018-02-07"), value: 159.54), + LineData(time: .string("2018-02-08"), value: 155.15), + LineData(time: .string("2018-02-09"), value: 156.41), + LineData(time: .string("2018-02-12"), value: 162.71), + LineData(time: .string("2018-02-13"), value: 164.34), + LineData(time: .string("2018-02-14"), value: 167.37), + LineData(time: .string("2018-02-15"), value: 172.99), + LineData(time: .string("2018-02-16"), value: 172.43), + LineData(time: .string("2018-02-20"), value: 171.85), + LineData(time: .string("2018-02-21"), value: 171.07), + LineData(time: .string("2018-02-22"), value: 172.50), + LineData(time: .string("2018-02-23"), value: 175.50), + LineData(time: .string("2018-02-26"), value: 178.97), + LineData(time: .string("2018-02-27"), value: 178.39), + LineData(time: .string("2018-02-28"), value: 178.12), + LineData(time: .string("2018-03-01"), value: 175.00), + LineData(time: .string("2018-03-02"), value: 176.21), + LineData(time: .string("2018-03-05"), value: 176.82), + LineData(time: .string("2018-03-06"), value: 176.67), + LineData(time: .string("2018-03-07"), value: 175.03), + LineData(time: .string("2018-03-08"), value: 176.94), + LineData(time: .string("2018-03-09"), value: 179.98), + LineData(time: .string("2018-03-12"), value: 181.72), + LineData(time: .string("2018-03-13"), value: 179.97), + LineData(time: .string("2018-03-14"), value: 178.44), + LineData(time: .string("2018-03-15"), value: 178.65), + LineData(time: .string("2018-03-16"), value: 178.02), + LineData(time: .string("2018-03-19"), value: 175.30), + LineData(time: .string("2018-03-20"), value: 175.24), + LineData(time: .string("2018-03-21"), value: 171.27), + LineData(time: .string("2018-03-22"), value: 168.85), + LineData(time: .string("2018-03-23"), value: 164.94), + LineData(time: .string("2018-03-26"), value: 172.77), + LineData(time: .string("2018-03-27"), value: 168.34), + LineData(time: .string("2018-03-28"), value: 166.48), + LineData(time: .string("2018-03-29"), value: 167.78), + LineData(time: .string("2018-04-02"), value: 166.68), + LineData(time: .string("2018-04-03"), value: 168.39), + LineData(time: .string("2018-04-04"), value: 171.61), + LineData(time: .string("2018-04-05"), value: 172.80), + LineData(time: .string("2018-04-06"), value: 168.38), + LineData(time: .string("2018-04-09"), value: 170.05), + LineData(time: .string("2018-04-10"), value: 173.25), + LineData(time: .string("2018-04-11"), value: 172.44), + LineData(time: .string("2018-04-12"), value: 174.14), + LineData(time: .string("2018-04-13"), value: 174.73), + LineData(time: .string("2018-04-16"), value: 175.82), + LineData(time: .string("2018-04-17"), value: 178.24), + LineData(time: .string("2018-04-18"), value: 177.84), + LineData(time: .string("2018-04-19"), value: 172.80), + LineData(time: .string("2018-04-20"), value: 165.72), + LineData(time: .string("2018-04-23"), value: 165.24), + LineData(time: .string("2018-04-24"), value: 162.94), + LineData(time: .string("2018-04-25"), value: 163.65), + LineData(time: .string("2018-04-26"), value: 164.22), + LineData(time: .string("2018-04-27"), value: 162.32), + LineData(time: .string("2018-04-30"), value: 165.26), + LineData(time: .string("2018-05-01"), value: 169.10), + LineData(time: .string("2018-05-02"), value: 176.57), + LineData(time: .string("2018-05-03"), value: 176.89), + LineData(time: .string("2018-05-04"), value: 183.83), + LineData(time: .string("2018-05-07"), value: 185.16), + LineData(time: .string("2018-05-08"), value: 186.05), + LineData(time: .string("2018-05-09"), value: 187.36), + LineData(time: .string("2018-05-10"), value: 190.04), + LineData(time: .string("2018-05-11"), value: 188.59), + LineData(time: .string("2018-05-14"), value: 188.15), + LineData(time: .string("2018-05-15"), value: 186.44), + LineData(time: .string("2018-05-16"), value: 188.18), + LineData(time: .string("2018-05-17"), value: 186.99), + LineData(time: .string("2018-05-18"), value: 186.31), + LineData(time: .string("2018-05-21"), value: 187.63), + LineData(time: .string("2018-05-22"), value: 187.16), + LineData(time: .string("2018-05-23"), value: 188.36), + LineData(time: .string("2018-05-24"), value: 188.15), + LineData(time: .string("2018-05-25"), value: 188.58), + LineData(time: .string("2018-05-29"), value: 187.90), + LineData(time: .string("2018-05-30"), value: 187.50), + LineData(time: .string("2018-05-31"), value: 186.87), + LineData(time: .string("2018-06-01"), value: 190.24), + LineData(time: .string("2018-06-04"), value: 191.83), + LineData(time: .string("2018-06-05"), value: 193.31), + LineData(time: .string("2018-06-06"), value: 193.98), + LineData(time: .string("2018-06-07"), value: 193.46), + LineData(time: .string("2018-06-08"), value: 191.70), + LineData(time: .string("2018-06-11"), value: 191.23), + LineData(time: .string("2018-06-12"), value: 192.28), + LineData(time: .string("2018-06-13"), value: 190.70), + LineData(time: .string("2018-06-14"), value: 190.80), + LineData(time: .string("2018-06-15"), value: 188.84), + LineData(time: .string("2018-06-18"), value: 188.74), + LineData(time: .string("2018-06-19"), value: 185.69), + LineData(time: .string("2018-06-20"), value: 186.50), + LineData(time: .string("2018-06-21"), value: 185.46), + LineData(time: .string("2018-06-22"), value: 184.92), + LineData(time: .string("2018-06-25"), value: 182.17), + LineData(time: .string("2018-06-26"), value: 184.43), + LineData(time: .string("2018-06-27"), value: 184.16), + LineData(time: .string("2018-06-28"), value: 185.50), + LineData(time: .string("2018-06-29"), value: 185.11), + LineData(time: .string("2018-07-02"), value: 187.18), + LineData(time: .string("2018-07-03"), value: 183.92), + LineData(time: .string("2018-07-05"), value: 185.40), + LineData(time: .string("2018-07-06"), value: 187.97), + LineData(time: .string("2018-07-09"), value: 190.58), + LineData(time: .string("2018-07-10"), value: 190.35), + LineData(time: .string("2018-07-11"), value: 187.88), + LineData(time: .string("2018-07-12"), value: 191.03), + LineData(time: .string("2018-07-13"), value: 191.33), + LineData(time: .string("2018-07-16"), value: 190.91), + LineData(time: .string("2018-07-17"), value: 191.45), + LineData(time: .string("2018-07-18"), value: 190.40), + LineData(time: .string("2018-07-19"), value: 191.88), + LineData(time: .string("2018-07-20"), value: 191.44), + LineData(time: .string("2018-07-23"), value: 191.61), + LineData(time: .string("2018-07-24"), value: 193.00), + LineData(time: .string("2018-07-25"), value: 194.82), + LineData(time: .string("2018-07-26"), value: 194.21), + LineData(time: .string("2018-07-27"), value: 190.98), + LineData(time: .string("2018-07-30"), value: 189.91), + LineData(time: .string("2018-07-31"), value: 190.29), + LineData(time: .string("2018-08-01"), value: 201.50), + LineData(time: .string("2018-08-02"), value: 207.39), + LineData(time: .string("2018-08-03"), value: 207.99), + LineData(time: .string("2018-08-06"), value: 209.07), + LineData(time: .string("2018-08-07"), value: 207.11), + LineData(time: .string("2018-08-08"), value: 207.25), + LineData(time: .string("2018-08-09"), value: 208.88), + LineData(time: .string("2018-08-10"), value: 207.53), + LineData(time: .string("2018-08-13"), value: 208.87), + LineData(time: .string("2018-08-14"), value: 209.75), + LineData(time: .string("2018-08-15"), value: 210.24), + LineData(time: .string("2018-08-16"), value: 213.32), + LineData(time: .string("2018-08-17"), value: 217.58), + LineData(time: .string("2018-08-20"), value: 215.46), + LineData(time: .string("2018-08-21"), value: 215.04), + LineData(time: .string("2018-08-22"), value: 215.05), + LineData(time: .string("2018-08-23"), value: 215.49), + LineData(time: .string("2018-08-24"), value: 216.16), + LineData(time: .string("2018-08-27"), value: 217.94), + LineData(time: .string("2018-08-28"), value: 219.70), + LineData(time: .string("2018-08-29"), value: 222.98), + LineData(time: .string("2018-08-30"), value: 225.03), + LineData(time: .string("2018-08-31"), value: 227.63), + LineData(time: .string("2018-09-04"), value: 228.36), + LineData(time: .string("2018-09-05"), value: 226.87), + LineData(time: .string("2018-09-06"), value: 223.10), + LineData(time: .string("2018-09-07"), value: 221.30), + LineData(time: .string("2018-09-10"), value: 218.33), + LineData(time: .string("2018-09-11"), value: 223.85), + LineData(time: .string("2018-09-12"), value: 221.07), + LineData(time: .string("2018-09-13"), value: 226.41), + LineData(time: .string("2018-09-14"), value: 223.84), + LineData(time: .string("2018-09-17"), value: 217.88), + LineData(time: .string("2018-09-18"), value: 218.24), + LineData(time: .string("2018-09-19"), value: 218.37), + LineData(time: .string("2018-09-20"), value: 220.03), + LineData(time: .string("2018-09-21"), value: 217.66), + LineData(time: .string("2018-09-24"), value: 220.79), + LineData(time: .string("2018-09-25"), value: 222.19), + LineData(time: .string("2018-09-26"), value: 220.42), + LineData(time: .string("2018-09-27"), value: 224.95), + LineData(time: .string("2018-09-28"), value: 225.74), + LineData(time: .string("2018-10-01"), value: 227.26), + LineData(time: .string("2018-10-02"), value: 229.28), + LineData(time: .string("2018-10-03"), value: 232.07), + LineData(time: .string("2018-10-04"), value: 227.99), + LineData(time: .string("2018-10-05"), value: 224.29), + LineData(time: .string("2018-10-08"), value: 223.77), + LineData(time: .string("2018-10-09"), value: 226.87), + LineData(time: .string("2018-10-10"), value: 216.36), + LineData(time: .string("2018-10-11"), value: 214.45), + LineData(time: .string("2018-10-12"), value: 222.11), + LineData(time: .string("2018-10-15"), value: 217.36), + LineData(time: .string("2018-10-16"), value: 222.15), + LineData(time: .string("2018-10-17"), value: 221.19), + LineData(time: .string("2018-10-18"), value: 216.02), + LineData(time: .string("2018-10-19"), value: 219.31), + LineData(time: .string("2018-10-22"), value: 220.65), + LineData(time: .string("2018-10-23"), value: 222.73), + LineData(time: .string("2018-10-24"), value: 215.09), + LineData(time: .string("2018-10-25"), value: 219.80), + LineData(time: .string("2018-10-26"), value: 216.30), + LineData(time: .string("2018-10-29"), value: 212.24), + LineData(time: .string("2018-10-30"), value: 213.30), + LineData(time: .string("2018-10-31"), value: 218.86), + LineData(time: .string("2018-11-01"), value: 222.22), + LineData(time: .string("2018-11-02"), value: 207.48), + LineData(time: .string("2018-11-05"), value: 201.59), + LineData(time: .string("2018-11-06"), value: 203.77), + LineData(time: .string("2018-11-07"), value: 209.95), + LineData(time: .string("2018-11-08"), value: 208.49), + LineData(time: .string("2018-11-09"), value: 204.47), + LineData(time: .string("2018-11-12"), value: 194.17), + LineData(time: .string("2018-11-13"), value: 192.23), + LineData(time: .string("2018-11-14"), value: 186.80), + LineData(time: .string("2018-11-15"), value: 191.41), + LineData(time: .string("2018-11-16"), value: 193.53), + LineData(time: .string("2018-11-19"), value: 185.86), + LineData(time: .string("2018-11-20"), value: 176.98), + LineData(time: .string("2018-11-21"), value: 176.78), + LineData(time: .string("2018-11-23"), value: 172.29), + LineData(time: .string("2018-11-26"), value: 174.62), + LineData(time: .string("2018-11-27"), value: 174.24), + LineData(time: .string("2018-11-28"), value: 180.94), + LineData(time: .string("2018-11-29"), value: 179.55), + LineData(time: .string("2018-11-30"), value: 178.58), + LineData(time: .string("2018-12-03"), value: 184.82), + LineData(time: .string("2018-12-04"), value: 176.69), + LineData(time: .string("2018-12-06"), value: 174.72), + LineData(time: .string("2018-12-07"), value: 168.49), + LineData(time: .string("2018-12-10"), value: 169.60), + LineData(time: .string("2018-12-11"), value: 168.63), + LineData(time: .string("2018-12-12"), value: 169.10), + LineData(time: .string("2018-12-13"), value: 170.95), + LineData(time: .string("2018-12-14"), value: 165.48), + LineData(time: .string("2018-12-17"), value: 163.94), + LineData(time: .string("2018-12-18"), value: 166.07), + LineData(time: .string("2018-12-19"), value: 160.89), + LineData(time: .string("2018-12-20"), value: 156.83), + LineData(time: .string("2018-12-21"), value: 150.73), + LineData(time: .string("2018-12-24"), value: 146.83), + LineData(time: .string("2018-12-26"), value: 157.17), + LineData(time: .string("2018-12-27"), value: 156.15), + LineData(time: .string("2018-12-28"), value: 156.23), + LineData(time: .string("2018-12-31"), value: 157.74), + LineData(time: .string("2019-01-02"), value: 157.92), + LineData(time: .string("2019-01-03"), value: 142.19), + LineData(time: .string("2019-01-04"), value: 148.26), + LineData(time: .string("2019-01-07"), value: 147.93), + LineData(time: .string("2019-01-08"), value: 150.75), + LineData(time: .string("2019-01-09"), value: 153.31), + LineData(time: .string("2019-01-10"), value: 153.80), + LineData(time: .string("2019-01-11"), value: 152.29), + LineData(time: .string("2019-01-14"), value: 150.00), + LineData(time: .string("2019-01-15"), value: 153.07), + LineData(time: .string("2019-01-16"), value: 154.94), + LineData(time: .string("2019-01-17"), value: 155.86), + LineData(time: .string("2019-01-18"), value: 156.82), + LineData(time: .string("2019-01-22"), value: 153.30), + LineData(time: .string("2019-01-23"), value: 153.92), + LineData(time: .string("2019-01-24"), value: 152.70), + LineData(time: .string("2019-01-25"), value: 157.76), + LineData(time: .string("2019-01-28"), value: 156.30), + LineData(time: .string("2019-01-29"), value: 154.68), + LineData(time: .string("2019-01-30"), value: 165.25), + LineData(time: .string("2019-01-31"), value: 166.44), + LineData(time: .string("2019-02-01"), value: 166.52), + LineData(time: .string("2019-02-04"), value: 171.25), + LineData(time: .string("2019-02-05"), value: 174.18), + LineData(time: .string("2019-02-06"), value: 174.24), + LineData(time: .string("2019-02-07"), value: 170.94), + LineData(time: .string("2019-02-08"), value: 170.41), + LineData(time: .string("2019-02-11"), value: 169.43), + LineData(time: .string("2019-02-12"), value: 170.89), + LineData(time: .string("2019-02-13"), value: 170.18), + LineData(time: .string("2019-02-14"), value: 170.80), + LineData(time: .string("2019-02-15"), value: 170.42), + LineData(time: .string("2019-02-19"), value: 170.93), + LineData(time: .string("2019-02-20"), value: 172.03), + LineData(time: .string("2019-02-21"), value: 171.06), + LineData(time: .string("2019-02-22"), value: 172.97), + LineData(time: .string("2019-02-25"), value: 174.23), + LineData(time: .string("2019-02-26"), value: 174.33), + LineData(time: .string("2019-02-27"), value: 174.87), + LineData(time: .string("2019-02-28"), value: 173.15), + LineData(time: .string("2019-03-01"), value: 174.97), + LineData(time: .string("2019-03-04"), value: 175.85), + LineData(time: .string("2019-03-05"), value: 175.53), + LineData(time: .string("2019-03-06"), value: 174.52), + LineData(time: .string("2019-03-07"), value: 172.50), + LineData(time: .string("2019-03-08"), value: 172.91), + LineData(time: .string("2019-03-11"), value: 178.90), + LineData(time: .string("2019-03-12"), value: 180.91), + LineData(time: .string("2019-03-13"), value: 181.71), + LineData(time: .string("2019-03-14"), value: 183.73), + LineData(time: .string("2019-03-15"), value: 186.12), + LineData(time: .string("2019-03-18"), value: 188.02), + LineData(time: .string("2019-03-19"), value: 186.53), + LineData(time: .string("2019-03-20"), value: 188.16), + LineData(time: .string("2019-03-21"), value: 195.09), + LineData(time: .string("2019-03-22"), value: 191.05), + LineData(time: .string("2019-03-25"), value: 188.74), + LineData(time: .string("2019-03-26"), value: 186.79), + LineData(time: .string("2019-03-27"), value: 188.47), + LineData(time: .string("2019-03-28"), value: 188.72), + LineData(time: .string("2019-03-29"), value: 189.95), + LineData(time: .string("2019-04-01"), value: 191.24), + LineData(time: .string("2019-04-02"), value: 194.02), + LineData(time: .string("2019-04-03"), value: 195.35), + LineData(time: .string("2019-04-04"), value: 195.69), + LineData(time: .string("2019-04-05"), value: 197.00), + LineData(time: .string("2019-04-08"), value: 200.10), + LineData(time: .string("2019-04-09"), value: 199.50), + LineData(time: .string("2019-04-10"), value: 200.62), + LineData(time: .string("2019-04-11"), value: 198.95), + LineData(time: .string("2019-04-12"), value: 198.87), + LineData(time: .string("2019-04-15"), value: 199.23), + LineData(time: .string("2019-04-16"), value: 199.25), + LineData(time: .string("2019-04-17"), value: 203.13), + LineData(time: .string("2019-04-18"), value: 203.86), + LineData(time: .string("2019-04-22"), value: 204.53), + LineData(time: .string("2019-04-23"), value: 207.48), + LineData(time: .string("2019-04-24"), value: 207.16), + LineData(time: .string("2019-04-25"), value: 205.28), + LineData(time: .string("2019-04-26"), value: 204.30), + LineData(time: .string("2019-04-29"), value: 204.61), + LineData(time: .string("2019-04-30"), value: 200.67), + LineData(time: .string("2019-05-01"), value: 210.52), + LineData(time: .string("2019-05-02"), value: 209.15), + LineData(time: .string("2019-05-03"), value: 211.75), + LineData(time: .string("2019-05-06"), value: 208.48), + LineData(time: .string("2019-05-07"), value: 202.86), + LineData(time: .string("2019-05-08"), value: 202.90), + LineData(time: .string("2019-05-09"), value: 200.72), + LineData(time: .string("2019-05-10"), value: 197.18), + LineData(time: .string("2019-05-13"), value: 185.72), + LineData(time: .string("2019-05-14"), value: 188.66), + LineData(time: .string("2019-05-15"), value: 190.92), + LineData(time: .string("2019-05-16"), value: 190.08), + LineData(time: .string("2019-05-17"), value: 189.00), + LineData(time: .string("2019-05-20"), value: 183.09), + LineData(time: .string("2019-05-21"), value: 186.60), + LineData(time: .string("2019-05-22"), value: 182.78), + LineData(time: .string("2019-05-23"), value: 179.66), + LineData(time: .string("2019-05-24"), value: 178.97), + LineData(time: .string("2019-05-28"), value: 179.11) + ] + series.setData(data: data) + self.series = series + } + +} diff --git a/ExampleSPM/LightweightCharts/Example/FloatingTooltipViewController.swift b/ExampleSPM/LightweightCharts/Example/FloatingTooltipViewController.swift new file mode 100644 index 0000000..d42206f --- /dev/null +++ b/ExampleSPM/LightweightCharts/Example/FloatingTooltipViewController.swift @@ -0,0 +1,435 @@ +import UIKit +import LightweightCharts + +class FloatingTooltipViewController: UIViewController { + + private var chart: LightweightCharts! + private var series: AreaSeries! + private let tooltipView = TooltipView(accentColor: UIColor(red: 0, green: 150/255.0, blue: 136/255.0, alpha: 1)) + private let legend = "Apple Inc." + + private var centerXConstraint: NSLayoutConstraint! + private var bottomConstraint: NSLayoutConstraint! + + override func viewDidLoad() { + super.viewDidLoad() + if #available(iOS 13.0, *) { + view.backgroundColor = .systemBackground + } else { + view.backgroundColor = .white + } + + setupUI() + setupData() + setupSubscription() + } + + private func setupUI() { + let options = ChartOptions( + layout: LayoutOptions( + background: .solid(color: "#ffffff"), + textColor: "#333" + ), + rightPriceScale: VisiblePriceScaleOptions( + scaleMargins: PriceScaleMargins( + top: 0.2, + bottom: 0.2 + ), + borderVisible: false + ), + timeScale: TimeScaleOptions(borderVisible: false), + crosshair: CrosshairOptions(vertLine: CrosshairLineOptions(labelVisible: false)), + grid: GridOptions( + verticalLines: GridLineOptions(color: "#ffffff"), + horizontalLines: GridLineOptions(color: "#eee") + ), + kineticScroll: KineticScrollOptions( + touch: false, mouse: false + ) + ) + let chart = LightweightCharts(options: options) + view.addSubview(chart) + chart.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + ]) + } else { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } + self.chart = chart + + view.addSubview(tooltipView) + + tooltipView.translatesAutoresizingMaskIntoConstraints = false + centerXConstraint = tooltipView.centerXAnchor.constraint(equalTo: chart.leadingAnchor) + bottomConstraint = tooltipView.bottomAnchor.constraint(equalTo: chart.topAnchor) + centerXConstraint.isActive = true + bottomConstraint.isActive = true + + tooltipView.isHidden = true + + view.bringSubviewToFront(tooltipView) + } + + private func setupData() { + let options = AreaSeriesOptions( + topColor: "rgba(0, 150, 136, 0.56)", + bottomColor: "rgba(0, 150, 136, 0.04)", + lineColor: "rgba(0, 150, 136, 1.0)", + lineWidth: .two, + lastPriceAnimation: .continuous + ) + let series = chart.addAreaSeries(options: options) + let data = [ + LineData(time: .string("2018-03-28"), value: 154), + LineData(time: .string("2018-03-29"), value: 154.2), + LineData(time: .string("2018-03-30"), value: 155.60001), + LineData(time: .string("2018-04-02"), value: 156.25), + LineData(time: .string("2018-04-03"), value: 156.25), + LineData(time: .string("2018-04-04"), value: 156.05), + LineData(time: .string("2018-04-05"), value: 158.05), + LineData(time: .string("2018-04-06"), value: 157.3), + LineData(time: .string("2018-04-09"), value: 144), + LineData(time: .string("2018-04-10"), value: 144.8), + LineData(time: .string("2018-04-11"), value: 143.5), + LineData(time: .string("2018-04-12"), value: 147.05), + LineData(time: .string("2018-04-13"), value: 144.85001), + LineData(time: .string("2018-04-16"), value: 145.39999), + LineData(time: .string("2018-04-17"), value: 147.3), + LineData(time: .string("2018-04-18"), value: 153.55), + LineData(time: .string("2018-04-19"), value: 150.95), + LineData(time: .string("2018-04-20"), value: 149.39999), + LineData(time: .string("2018-04-23"), value: 148.5), + LineData(time: .string("2018-04-24"), value: 146.60001), + LineData(time: .string("2018-04-25"), value: 144.45), + LineData(time: .string("2018-04-26"), value: 145.60001), + LineData(time: .string("2018-04-27"), value: 144.3), + LineData(time: .string("2018-04-30"), value: 144), + LineData(time: .string("2018-05-02"), value: 147.3), + LineData(time: .string("2018-05-03"), value: 144.2), + LineData(time: .string("2018-05-04"), value: 141.64999), + LineData(time: .string("2018-05-07"), value: 141.89999), + LineData(time: .string("2018-05-08"), value: 140.39999), + LineData(time: .string("2018-05-10"), value: 139.8), + LineData(time: .string("2018-05-11"), value: 137.5), + LineData(time: .string("2018-05-14"), value: 136.14999), + LineData(time: .string("2018-05-15"), value: 138), + LineData(time: .string("2018-05-16"), value: 137.95), + LineData(time: .string("2018-05-17"), value: 137.95), + LineData(time: .string("2018-05-18"), value: 136.75), + LineData(time: .string("2018-05-21"), value: 136.2), + LineData(time: .string("2018-05-22"), value: 135), + LineData(time: .string("2018-05-23"), value: 132.55), + LineData(time: .string("2018-05-24"), value: 132.7), + LineData(time: .string("2018-05-25"), value: 132.2), + LineData(time: .string("2018-05-28"), value: 131.55), + LineData(time: .string("2018-05-29"), value: 131.85001), + LineData(time: .string("2018-05-30"), value: 139.85001), + LineData(time: .string("2018-05-31"), value: 140.8), + LineData(time: .string("2018-06-01"), value: 139.64999), + LineData(time: .string("2018-06-04"), value: 137.10001), + LineData(time: .string("2018-06-05"), value: 139.25), + LineData(time: .string("2018-06-06"), value: 141.3), + LineData(time: .string("2018-06-07"), value: 145), + LineData(time: .string("2018-06-08"), value: 143.89999), + LineData(time: .string("2018-06-11"), value: 142.7), + LineData(time: .string("2018-06-13"), value: 144.05), + LineData(time: .string("2018-06-14"), value: 143.55), + LineData(time: .string("2018-06-15"), value: 140.5), + LineData(time: .string("2018-06-18"), value: 139.64999), + LineData(time: .string("2018-06-19"), value: 138), + LineData(time: .string("2018-06-20"), value: 141), + LineData(time: .string("2018-06-21"), value: 140.55), + LineData(time: .string("2018-06-22"), value: 140.55), + LineData(time: .string("2018-06-25"), value: 140.75), + LineData(time: .string("2018-06-26"), value: 140.64999), + LineData(time: .string("2018-06-27"), value: 141.14999), + LineData(time: .string("2018-06-28"), value: 139.8), + LineData(time: .string("2018-06-29"), value: 139.8), + LineData(time: .string("2018-07-02"), value: 140.14999), + LineData(time: .string("2018-07-03"), value: 143.05), + LineData(time: .string("2018-07-04"), value: 140), + LineData(time: .string("2018-07-05"), value: 129.2), + LineData(time: .string("2018-07-06"), value: 129.55), + LineData(time: .string("2018-07-09"), value: 128.3), + LineData(time: .string("2018-07-10"), value: 126.55), + LineData(time: .string("2018-07-11"), value: 124.3), + LineData(time: .string("2018-07-12"), value: 124.8), + LineData(time: .string("2018-07-13"), value: 123.25), + LineData(time: .string("2018-07-16"), value: 123), + LineData(time: .string("2018-07-17"), value: 124.25), + LineData(time: .string("2018-07-18"), value: 123), + LineData(time: .string("2018-07-19"), value: 121), + LineData(time: .string("2018-07-20"), value: 121.45), + LineData(time: .string("2018-07-23"), value: 123.8), + LineData(time: .string("2018-07-24"), value: 122.15), + LineData(time: .string("2018-07-25"), value: 121.3), + LineData(time: .string("2018-07-26"), value: 122.7), + LineData(time: .string("2018-07-27"), value: 122.2), + LineData(time: .string("2018-07-30"), value: 121.7), + LineData(time: .string("2018-07-31"), value: 122.95), + LineData(time: .string("2018-08-01"), value: 121), + LineData(time: .string("2018-08-02"), value: 116), + LineData(time: .string("2018-08-03"), value: 118.1), + LineData(time: .string("2018-08-06"), value: 114.3), + LineData(time: .string("2018-08-07"), value: 114.25), + LineData(time: .string("2018-08-08"), value: 111.85), + LineData(time: .string("2018-08-09"), value: 109.7), + LineData(time: .string("2018-08-10"), value: 105), + LineData(time: .string("2018-08-13"), value: 105.75), + LineData(time: .string("2018-08-14"), value: 107.25), + LineData(time: .string("2018-08-15"), value: 107.4), + LineData(time: .string("2018-08-16"), value: 110.5), + LineData(time: .string("2018-08-17"), value: 109), + LineData(time: .string("2018-08-20"), value: 108.95), + LineData(time: .string("2018-08-21"), value: 108.35), + LineData(time: .string("2018-08-22"), value: 108.6), + LineData(time: .string("2018-08-23"), value: 105.65), + LineData(time: .string("2018-08-24"), value: 104.45), + LineData(time: .string("2018-08-27"), value: 106.2), + LineData(time: .string("2018-08-28"), value: 106.55), + LineData(time: .string("2018-08-29"), value: 111.8), + LineData(time: .string("2018-08-30"), value: 115.5), + LineData(time: .string("2018-08-31"), value: 115.5), + LineData(time: .string("2018-09-03"), value: 114.55), + LineData(time: .string("2018-09-04"), value: 112.75), + LineData(time: .string("2018-09-05"), value: 111.5), + LineData(time: .string("2018-09-06"), value: 108.1), + LineData(time: .string("2018-09-07"), value: 108.55), + LineData(time: .string("2018-09-10"), value: 106.5), + LineData(time: .string("2018-09-11"), value: 105.1), + LineData(time: .string("2018-09-12"), value: 107.2), + LineData(time: .string("2018-09-13"), value: 107.1), + LineData(time: .string("2018-09-14"), value: 105.75), + LineData(time: .string("2018-09-17"), value: 106.05), + LineData(time: .string("2018-09-18"), value: 109.15), + LineData(time: .string("2018-09-19"), value: 111.4), + LineData(time: .string("2018-09-20"), value: 111), + LineData(time: .string("2018-09-21"), value: 111), + LineData(time: .string("2018-09-24"), value: 108.95), + LineData(time: .string("2018-09-25"), value: 106.65), + LineData(time: .string("2018-09-26"), value: 106.7), + LineData(time: .string("2018-09-27"), value: 107.05), + LineData(time: .string("2018-09-28"), value: 106.55), + LineData(time: .string("2018-10-01"), value: 106.2), + LineData(time: .string("2018-10-02"), value: 106.4), + LineData(time: .string("2018-10-03"), value: 107.1), + LineData(time: .string("2018-10-04"), value: 106.4), + LineData(time: .string("2018-10-05"), value: 104.65), + LineData(time: .string("2018-10-08"), value: 102.65), + LineData(time: .string("2018-10-09"), value: 102.1), + LineData(time: .string("2018-10-10"), value: 102.15), + LineData(time: .string("2018-10-11"), value: 100.9), + LineData(time: .string("2018-10-12"), value: 102), + LineData(time: .string("2018-10-15"), value: 100.15), + LineData(time: .string("2018-10-16"), value: 99), + LineData(time: .string("2018-10-17"), value: 98), + LineData(time: .string("2018-10-18"), value: 96), + LineData(time: .string("2018-10-19"), value: 95.5), + LineData(time: .string("2018-10-22"), value: 92.400002), + LineData(time: .string("2018-10-23"), value: 92.300003), + LineData(time: .string("2018-10-24"), value: 92.900002), + LineData(time: .string("2018-10-25"), value: 91.849998), + LineData(time: .string("2018-10-26"), value: 91.599998), + LineData(time: .string("2018-10-29"), value: 94.050003), + LineData(time: .string("2018-10-30"), value: 98.25), + LineData(time: .string("2018-10-31"), value: 97.25), + LineData(time: .string("2018-11-01"), value: 96.879997), + LineData(time: .string("2018-11-02"), value: 101.78), + LineData(time: .string("2018-11-06"), value: 102.4), + LineData(time: .string("2018-11-07"), value: 100.6), + LineData(time: .string("2018-11-08"), value: 98.5), + LineData(time: .string("2018-11-09"), value: 95.139999), + LineData(time: .string("2018-11-12"), value: 96.900002), + LineData(time: .string("2018-11-13"), value: 97.400002), + LineData(time: .string("2018-11-14"), value: 103.3), + LineData(time: .string("2018-11-15"), value: 102.74), + LineData(time: .string("2018-11-16"), value: 101.2), + LineData(time: .string("2018-11-19"), value: 98.720001), + LineData(time: .string("2018-11-20"), value: 102.2), + LineData(time: .string("2018-11-21"), value: 108.8), + LineData(time: .string("2018-11-22"), value: 109.9), + LineData(time: .string("2018-11-23"), value: 113.74), + LineData(time: .string("2018-11-26"), value: 110.9), + LineData(time: .string("2018-11-27"), value: 113.28), + LineData(time: .string("2018-11-28"), value: 113.6), + LineData(time: .string("2018-11-29"), value: 113.14), + LineData(time: .string("2018-11-30"), value: 114.4), + LineData(time: .string("2018-12-03"), value: 111.84), + LineData(time: .string("2018-12-04"), value: 106.7), + LineData(time: .string("2018-12-05"), value: 107.8), + LineData(time: .string("2018-12-06"), value: 106.44), + LineData(time: .string("2018-12-07"), value: 103.7), + LineData(time: .string("2018-12-10"), value: 101.02), + LineData(time: .string("2018-12-11"), value: 102.72), + LineData(time: .string("2018-12-12"), value: 101.8), + LineData(time: .string("2018-12-13"), value: 102), + LineData(time: .string("2018-12-14"), value: 102.1), + LineData(time: .string("2018-12-17"), value: 101.04), + LineData(time: .string("2018-12-18"), value: 101.6), + LineData(time: .string("2018-12-19"), value: 102), + LineData(time: .string("2018-12-20"), value: 102.02), + LineData(time: .string("2018-12-21"), value: 102.2), + LineData(time: .string("2018-12-24"), value: 102.1), + LineData(time: .string("2018-12-25"), value: 100.8), + LineData(time: .string("2018-12-26"), value: 101.02), + LineData(time: .string("2018-12-27"), value: 100.5), + LineData(time: .string("2018-12-28"), value: 101), + LineData(time: .string("2019-01-03"), value: 101.5), + LineData(time: .string("2019-01-04"), value: 101.1), + LineData(time: .string("2019-01-08"), value: 101.1), + LineData(time: .string("2019-01-09"), value: 102.06), + LineData(time: .string("2019-01-10"), value: 105.14), + LineData(time: .string("2019-01-11"), value: 104.66), + LineData(time: .string("2019-01-14"), value: 106.22), + LineData(time: .string("2019-01-15"), value: 106.98), + LineData(time: .string("2019-01-16"), value: 108.4), + LineData(time: .string("2019-01-17"), value: 109.06), + LineData(time: .string("2019-01-18"), value: 107), + LineData(time: .string("2019-01-21"), value: 105.8), + LineData(time: .string("2019-01-22"), value: 105.24), + LineData(time: .string("2019-01-23"), value: 105.4), + LineData(time: .string("2019-01-24"), value: 105.38), + LineData(time: .string("2019-01-25"), value: 105.7), + LineData(time: .string("2019-01-28"), value: 105.8), + LineData(time: .string("2019-01-29"), value: 106.1), + LineData(time: .string("2019-01-30"), value: 108.6), + LineData(time: .string("2019-01-31"), value: 107.92), + LineData(time: .string("2019-02-01"), value: 105.22), + LineData(time: .string("2019-02-04"), value: 102.44), + LineData(time: .string("2019-02-05"), value: 102.26), + LineData(time: .string("2019-02-06"), value: 102), + LineData(time: .string("2019-02-07"), value: 101.62), + LineData(time: .string("2019-02-08"), value: 101.9), + LineData(time: .string("2019-02-11"), value: 101.78), + LineData(time: .string("2019-02-12"), value: 102.7), + LineData(time: .string("2019-02-13"), value: 100.14), + LineData(time: .string("2019-02-14"), value: 101.36), + LineData(time: .string("2019-02-15"), value: 101.62), + LineData(time: .string("2019-02-18"), value: 100.74), + LineData(time: .string("2019-02-19"), value: 100), + LineData(time: .string("2019-02-20"), value: 100.04), + LineData(time: .string("2019-02-21"), value: 100), + LineData(time: .string("2019-02-22"), value: 100.12), + LineData(time: .string("2019-02-25"), value: 100.04), + LineData(time: .string("2019-02-26"), value: 98.980003), + LineData(time: .string("2019-02-27"), value: 97.699997), + LineData(time: .string("2019-02-28"), value: 97.099998), + LineData(time: .string("2019-03-01"), value: 96.760002), + LineData(time: .string("2019-03-04"), value: 98.360001), + LineData(time: .string("2019-03-05"), value: 96.260002), + LineData(time: .string("2019-03-06"), value: 98.120003), + LineData(time: .string("2019-03-07"), value: 99.68), + LineData(time: .string("2019-03-11"), value: 102.1), + LineData(time: .string("2019-03-12"), value: 100.22), + LineData(time: .string("2019-03-13"), value: 100.5), + LineData(time: .string("2019-03-14"), value: 99.660004), + LineData(time: .string("2019-03-15"), value: 100.08), + LineData(time: .string("2019-03-18"), value: 99.919998), + LineData(time: .string("2019-03-19"), value: 99.459999), + LineData(time: .string("2019-03-20"), value: 98.220001), + LineData(time: .string("2019-03-21"), value: 97.300003), + LineData(time: .string("2019-03-22"), value: 97.660004), + LineData(time: .string("2019-03-25"), value: 97), + LineData(time: .string("2019-03-26"), value: 97.019997), + LineData(time: .string("2019-03-27"), value: 96.099998), + LineData(time: .string("2019-03-28"), value: 96.699997), + LineData(time: .string("2019-03-29"), value: 96.300003), + LineData(time: .string("2019-04-01"), value: 97.779999), + LineData(time: .string("2019-04-02"), value: 98.360001), + LineData(time: .string("2019-04-03"), value: 98.5), + LineData(time: .string("2019-04-04"), value: 98.360001), + LineData(time: .string("2019-04-05"), value: 99.540001), + LineData(time: .string("2019-04-08"), value: 98.580002), + LineData(time: .string("2019-04-09"), value: 97.239998), + LineData(time: .string("2019-04-10"), value: 97.32), + LineData(time: .string("2019-04-11"), value: 98.400002), + LineData(time: .string("2019-04-12"), value: 98.220001), + LineData(time: .string("2019-04-15"), value: 98.720001), + LineData(time: .string("2019-04-16"), value: 99.120003), + LineData(time: .string("2019-04-17"), value: 98.620003), + LineData(time: .string("2019-04-18"), value: 98), + LineData(time: .string("2019-04-19"), value: 97.599998), + LineData(time: .string("2019-04-22"), value: 97.599998), + LineData(time: .string("2019-04-23"), value: 96.800003), + LineData(time: .string("2019-04-24"), value: 96.32), + LineData(time: .string("2019-04-25"), value: 96.339996), + LineData(time: .string("2019-04-26"), value: 97.120003), + LineData(time: .string("2019-04-29"), value: 96.980003), + LineData(time: .string("2019-04-30"), value: 96.32), + LineData(time: .string("2019-05-02"), value: 96.860001), + LineData(time: .string("2019-05-03"), value: 96.699997), + LineData(time: .string("2019-05-06"), value: 94.940002), + LineData(time: .string("2019-05-07"), value: 94.5), + LineData(time: .string("2019-05-08"), value: 94.239998), + LineData(time: .string("2019-05-10"), value: 92.900002), + LineData(time: .string("2019-05-13"), value: 91.279999), + LineData(time: .string("2019-05-14"), value: 91.599998), + LineData(time: .string("2019-05-15"), value: 90.080002), + LineData(time: .string("2019-05-16"), value: 91.68), + LineData(time: .string("2019-05-17"), value: 91.959999), + LineData(time: .string("2019-05-20"), value: 91.080002), + LineData(time: .string("2019-05-21"), value: 90.760002), + LineData(time: .string("2019-05-22"), value: 91), + LineData(time: .string("2019-05-23"), value: 90.739998), + LineData(time: .string("2019-05-24"), value: 91), + LineData(time: .string("2019-05-27"), value: 91.199997), + LineData(time: .string("2019-05-28"), value: 90.68), + LineData(time: .string("2019-05-29"), value: 91.120003), + LineData(time: .string("2019-05-30"), value: 90.419998), + LineData(time: .string("2019-05-31"), value: 93.800003), + LineData(time: .string("2019-06-03"), value: 96.800003), + LineData(time: .string("2019-06-04"), value: 96.34), + LineData(time: .string("2019-06-05"), value: 95.94) + ] + series.setData(data: data) + self.series = series + } + + private func setupSubscription() { + chart.delegate = self + chart.subscribeCrosshairMove() + } + +} + +// MARK: - ChartDelegate +extension FloatingTooltipViewController: ChartDelegate { + + func didClick(onChart chart: ChartApi, parameters: MouseEventParams) { + + } + + func didCrosshairMove(onChart chart: ChartApi, parameters: MouseEventParams) { + if case let .businessDay(date) = parameters.time, + let point = parameters.point, + case let .barPrice(price) = parameters.price(forSeries: series) { + self.series.priceToCoordinate(price: price) { [weak self] in + guard let self = self else { return } + if let coordinate = $0 { + let dateString = "\(date.year) - \(date.month) - \(date.day)" + self.tooltipView.update(title: self.legend, price: price, date: dateString) + self.tooltipView.isHidden = false + self.centerXConstraint.constant = CGFloat(point.x) + self.bottomConstraint.constant = CGFloat(coordinate) - 16 + } + } + } else { + self.tooltipView.isHidden = true + } + } + + func didVisibleTimeRangeChange(onChart chart: ChartApi, parameters: TimeRange?) { + + } + +} diff --git a/ExampleSPM/LightweightCharts/Example/GoToRealtimeButtonViewController.swift b/ExampleSPM/LightweightCharts/Example/GoToRealtimeButtonViewController.swift new file mode 100644 index 0000000..f5a8c55 --- /dev/null +++ b/ExampleSPM/LightweightCharts/Example/GoToRealtimeButtonViewController.swift @@ -0,0 +1,265 @@ +import UIKit +import LightweightCharts + +class GoToRealtimeButtonViewController: UIViewController { + + private var chart: LightweightCharts! + private var series: AreaSeries! + private var timeScale: TimeScaleApi! + private let button = UIButton() + + override func viewDidLoad() { + super.viewDidLoad() + if #available(iOS 13.0, *) { + view.backgroundColor = .systemBackground + } else { + view.backgroundColor = .white + } + + setupUI() + setupData() + timeScale = chart.timeScale() + timeScale.scrollToPosition(position: -20, animated: false) + setupSubscription() + } + + private func setupUI() { + let options = ChartOptions( + rightPriceScale: VisiblePriceScaleOptions(scaleMargins: PriceScaleMargins(top: 0.2, bottom: 0.1)), + timeScale: TimeScaleOptions(rightOffset: 2) + ) + let chart = LightweightCharts(options: options) + view.addSubview(chart) + chart.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + ]) + } else { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } + self.chart = chart + + button.setTitle("⏩", for: .normal) + button.tintColor = .darkText + button.titleLabel?.font = .systemFont(ofSize: 32) + button.addTarget(self, action: #selector(buttonTap), for: .touchUpInside) + view.addSubview(button) + button.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + button.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -64), + button.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -32) + ]) + } else { + NSLayoutConstraint.activate([ + button.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -64), + button.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -32) + ]) + } + } + + private func setupData() { + let options = AreaSeriesOptions( + topColor: "rgba(245, 124, 0, 0.4)", + bottomColor: "rgba(245, 124, 0, 0.4)", + lineColor: "rgba(245, 124, 0, 1)", + lineWidth: .two + ) + let series = chart.addAreaSeries(options: options) + let data = [ + LineData(time: .string("2016-07-18"), value: 26.10), + LineData(time: .string("2016-07-25"), value: 26.19), + LineData(time: .string("2016-08-01"), value: 26.24), + LineData(time: .string("2016-08-08"), value: 26.22), + LineData(time: .string("2016-08-15"), value: 25.98), + LineData(time: .string("2016-08-22"), value: 25.85), + LineData(time: .string("2016-08-29"), value: 25.98), + LineData(time: .string("2016-09-05"), value: 25.71), + LineData(time: .string("2016-09-12"), value: 25.84), + LineData(time: .string("2016-09-19"), value: 25.89), + LineData(time: .string("2016-09-26"), value: 25.65), + LineData(time: .string("2016-10-03"), value: 25.69), + LineData(time: .string("2016-10-10"), value: 25.67), + LineData(time: .string("2016-10-17"), value: 26.11), + LineData(time: .string("2016-10-24"), value: 25.80), + LineData(time: .string("2016-10-31"), value: 25.70), + LineData(time: .string("2016-11-07"), value: 25.40), + LineData(time: .string("2016-11-14"), value: 25.32), + LineData(time: .string("2016-11-21"), value: 25.48), + LineData(time: .string("2016-11-28"), value: 25.08), + LineData(time: .string("2016-12-05"), value: 25.06), + LineData(time: .string("2016-12-12"), value: 25.11), + LineData(time: .string("2016-12-19"), value: 25.34), + LineData(time: .string("2016-12-26"), value: 25.20), + LineData(time: .string("2017-01-02"), value: 25.33), + LineData(time: .string("2017-01-09"), value: 25.56), + LineData(time: .string("2017-01-16"), value: 25.32), + LineData(time: .string("2017-01-23"), value: 25.71), + LineData(time: .string("2017-01-30"), value: 25.85), + LineData(time: .string("2017-02-06"), value: 25.77), + LineData(time: .string("2017-02-13"), value: 25.94), + LineData(time: .string("2017-02-20"), value: 25.67), + LineData(time: .string("2017-02-27"), value: 25.60), + LineData(time: .string("2017-03-06"), value: 25.54), + LineData(time: .string("2017-03-13"), value: 25.84), + LineData(time: .string("2017-03-20"), value: 25.96), + LineData(time: .string("2017-03-27"), value: 25.90), + LineData(time: .string("2017-04-03"), value: 25.97), + LineData(time: .string("2017-04-10"), value: 26.00), + LineData(time: .string("2017-04-17"), value: 26.13), + LineData(time: .string("2017-04-24"), value: 26.02), + LineData(time: .string("2017-05-01"), value: 26.30), + LineData(time: .string("2017-05-08"), value: 26.27), + LineData(time: .string("2017-05-15"), value: 26.24), + LineData(time: .string("2017-05-22"), value: 26.02), + LineData(time: .string("2017-05-29"), value: 26.20), + LineData(time: .string("2017-06-05"), value: 26.12), + LineData(time: .string("2017-06-12"), value: 26.20), + LineData(time: .string("2017-06-19"), value: 26.46), + LineData(time: .string("2017-06-26"), value: 26.39), + LineData(time: .string("2017-07-03"), value: 26.52), + LineData(time: .string("2017-07-10"), value: 26.57), + LineData(time: .string("2017-07-17"), value: 26.65), + LineData(time: .string("2017-07-24"), value: 26.45), + LineData(time: .string("2017-07-31"), value: 26.37), + LineData(time: .string("2017-08-07"), value: 26.13), + LineData(time: .string("2017-08-14"), value: 26.21), + LineData(time: .string("2017-08-21"), value: 26.31), + LineData(time: .string("2017-08-28"), value: 26.33), + LineData(time: .string("2017-09-04"), value: 26.38), + LineData(time: .string("2017-09-11"), value: 26.38), + LineData(time: .string("2017-09-18"), value: 26.50), + LineData(time: .string("2017-09-25"), value: 26.39), + LineData(time: .string("2017-10-02"), value: 25.95), + LineData(time: .string("2017-10-09"), value: 26.15), + LineData(time: .string("2017-10-16"), value: 26.43), + LineData(time: .string("2017-10-23"), value: 26.22), + LineData(time: .string("2017-10-30"), value: 26.14), + LineData(time: .string("2017-11-06"), value: 26.08), + LineData(time: .string("2017-11-13"), value: 26.27), + LineData(time: .string("2017-11-20"), value: 26.30), + LineData(time: .string("2017-11-27"), value: 25.92), + LineData(time: .string("2017-12-04"), value: 26.10), + LineData(time: .string("2017-12-11"), value: 25.88), + LineData(time: .string("2017-12-18"), value: 25.82), + LineData(time: .string("2017-12-25"), value: 25.82), + LineData(time: .string("2018-01-01"), value: 25.81), + LineData(time: .string("2018-01-08"), value: 25.95), + LineData(time: .string("2018-01-15"), value: 26.03), + LineData(time: .string("2018-01-22"), value: 26.04), + LineData(time: .string("2018-01-29"), value: 25.96), + LineData(time: .string("2018-02-05"), value: 25.99), + LineData(time: .string("2018-02-12"), value: 26.00), + LineData(time: .string("2018-02-19"), value: 26.06), + LineData(time: .string("2018-02-26"), value: 25.77), + LineData(time: .string("2018-03-05"), value: 25.81), + LineData(time: .string("2018-03-12"), value: 25.88), + LineData(time: .string("2018-03-19"), value: 25.72), + LineData(time: .string("2018-03-26"), value: 25.75), + LineData(time: .string("2018-04-02"), value: 25.70), + LineData(time: .string("2018-04-09"), value: 25.73), + LineData(time: .string("2018-04-16"), value: 25.74), + LineData(time: .string("2018-04-23"), value: 25.69), + LineData(time: .string("2018-04-30"), value: 25.76), + LineData(time: .string("2018-05-07"), value: 25.89), + LineData(time: .string("2018-05-14"), value: 25.89), + LineData(time: .string("2018-05-21"), value: 26.00), + LineData(time: .string("2018-05-28"), value: 25.79), + LineData(time: .string("2018-06-04"), value: 26.11), + LineData(time: .string("2018-06-11"), value: 26.43), + LineData(time: .string("2018-06-18"), value: 26.30), + LineData(time: .string("2018-06-25"), value: 26.58), + LineData(time: .string("2018-07-02"), value: 26.33), + LineData(time: .string("2018-07-09"), value: 26.33), + LineData(time: .string("2018-07-16"), value: 26.32), + LineData(time: .string("2018-07-23"), value: 26.20), + LineData(time: .string("2018-07-30"), value: 26.03), + LineData(time: .string("2018-08-06"), value: 26.15), + LineData(time: .string("2018-08-13"), value: 26.17), + LineData(time: .string("2018-08-20"), value: 26.28), + LineData(time: .string("2018-08-27"), value: 25.86), + LineData(time: .string("2018-09-03"), value: 25.69), + LineData(time: .string("2018-09-10"), value: 25.69), + LineData(time: .string("2018-09-17"), value: 25.64), + LineData(time: .string("2018-09-24"), value: 25.67), + LineData(time: .string("2018-10-01"), value: 25.55), + LineData(time: .string("2018-10-08"), value: 25.59), + LineData(time: .string("2018-10-15"), value: 26.19), + LineData(time: .string("2018-10-22"), value: 25.81), + LineData(time: .string("2018-10-29"), value: 25.74), + LineData(time: .string("2018-11-05"), value: 25.75), + LineData(time: .string("2018-11-12"), value: 25.75), + LineData(time: .string("2018-11-19"), value: 25.72), + LineData(time: .string("2018-11-26"), value: 25.41), + LineData(time: .string("2018-12-03"), value: 25.39), + LineData(time: .string("2018-12-10"), value: 25.52), + LineData(time: .string("2018-12-17"), value: 25.66), + LineData(time: .string("2018-12-24"), value: 25.68), + LineData(time: .string("2018-12-31"), value: 25.71), + LineData(time: .string("2019-01-07"), value: 25.92), + LineData(time: .string("2019-01-14"), value: 25.60), + LineData(time: .string("2019-01-21"), value: 25.80), + LineData(time: .string("2019-01-28"), value: 25.60), + LineData(time: .string("2019-02-04"), value: 25.72), + LineData(time: .string("2019-02-11"), value: 25.89), + LineData(time: .string("2019-02-18"), value: 26.00), + LineData(time: .string("2019-02-25"), value: 25.86), + LineData(time: .string("2019-03-04"), value: 25.94), + LineData(time: .string("2019-03-11"), value: 26.11), + LineData(time: .string("2019-03-18"), value: 25.88), + LineData(time: .string("2019-03-25"), value: 25.77), + LineData(time: .string("2019-04-01"), value: 26.16), + LineData(time: .string("2019-04-08"), value: 26.04), + LineData(time: .string("2019-04-15"), value: 26.00), + LineData(time: .string("2019-04-22"), value: 25.88), + LineData(time: .string("2019-04-29"), value: 26.02), + LineData(time: .string("2019-05-06"), value: 26.08), + LineData(time: .string("2019-05-13"), value: 26.09), + LineData(time: .string("2019-05-20"), value: 26.16), + LineData(time: .string("2019-05-27"), value: 26.23) + ] + series.setData(data: data) + self.series = series + } + + @objc private func buttonTap(_ sender: UIButton) { + timeScale.scrollToRealTime() + } + + private func setupSubscription() { + timeScale.delegate = self + timeScale.subscribeVisibleTimeRangeChange() + } + +} + +// MARK: - TimeScaleDelegate +extension GoToRealtimeButtonViewController: TimeScaleDelegate { + func didVisibleTimeRangeChange(onTimeScale timeScale: TimeScaleApi, parameters: TimeRange?) { + timeScale.scrollPosition { [weak self] position in + let isHidden = (position ?? 0) >= 0 + if !isHidden { + self?.button.isHidden = false + } + UIView.animate(withDuration: 0.33, animations: { + self?.button.alpha = isHidden ? 0 : 1 + }, completion: { _ in + self?.button.isHidden = isHidden + }) + } + } + + func didVisibleLogicalRangeChange(onTimeScale timeScale: TimeScaleApi, parameters: LogicalRange?) { + + } + +} diff --git a/ExampleSPM/LightweightCharts/Example/IntradayDataViewController.swift b/ExampleSPM/LightweightCharts/Example/IntradayDataViewController.swift new file mode 100644 index 0000000..df69d8d --- /dev/null +++ b/ExampleSPM/LightweightCharts/Example/IntradayDataViewController.swift @@ -0,0 +1,209 @@ +import UIKit +import LightweightCharts + +class IntradayDataViewController: UIViewController { + + private var chart: LightweightCharts! + private var series: LineSeries! + + override func viewDidLoad() { + super.viewDidLoad() + if #available(iOS 13.0, *) { + view.backgroundColor = .systemBackground + } else { + view.backgroundColor = .white + } + + setupUI() + setupData() + } + + private func setupUI() { + let options = ChartOptions( + layout: LayoutOptions(backgroundColor: "#ffffff", textColor: "rgba(33, 56, 77, 1)"), + timeScale: TimeScaleOptions(timeVisible: true, secondsVisible: false), + grid: GridOptions( + verticalLines: GridLineOptions(color: "rgba(197, 203, 206, 0.7)"), + horizontalLines: GridLineOptions(color: "rgba(197, 203, 206, 0.7)") + ) + ) + let chart = LightweightCharts(options: options) + view.addSubview(chart) + chart.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + ]) + } else { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } + self.chart = chart + } + + private func setupData() { + let series = chart.addLineSeries(options: nil) + let data = [ + LineData(time: .utc(timestamp: 1556877600), value: 230.12), + LineData(time: .utc(timestamp: 1556881200), value: 230.24), + LineData(time: .utc(timestamp: 1556884800), value: 230.63), + LineData(time: .utc(timestamp: 1556888400), value: 231.35), + LineData(time: .utc(timestamp: 1556892000), value: 232.24), + LineData(time: .utc(timestamp: 1556895600), value: 232.52), + LineData(time: .utc(timestamp: 1557126000), value: 228.71), + LineData(time: .utc(timestamp: 1557129600), value: 228.88), + LineData(time: .utc(timestamp: 1557133200), value: 228.18), + LineData(time: .utc(timestamp: 1557136800), value: 228.89), + LineData(time: .utc(timestamp: 1557140400), value: 229.05), + LineData(time: .utc(timestamp: 1557144000), value: 229.46), + LineData(time: .utc(timestamp: 1557147600), value: 230.98), + LineData(time: .utc(timestamp: 1557151200), value: 231.71), + LineData(time: .utc(timestamp: 1557154800), value: 232.8), + LineData(time: .utc(timestamp: 1557212400), value: 233.1), + LineData(time: .utc(timestamp: 1557216000), value: 232.9), + LineData(time: .utc(timestamp: 1557219600), value: 232.9), + LineData(time: .utc(timestamp: 1557223200), value: 232.76), + LineData(time: .utc(timestamp: 1557226800), value: 232.41), + LineData(time: .utc(timestamp: 1557230400), value: 231.2), + LineData(time: .utc(timestamp: 1557234000), value: 230.83), + LineData(time: .utc(timestamp: 1557237600), value: 230.57), + LineData(time: .utc(timestamp: 1557241200), value: 231.49), + LineData(time: .utc(timestamp: 1557298800), value: 231.5), + LineData(time: .utc(timestamp: 1557302400), value: 230.87), + LineData(time: .utc(timestamp: 1557306000), value: 229.79), + LineData(time: .utc(timestamp: 1557309600), value: 230.06), + LineData(time: .utc(timestamp: 1557313200), value: 230.53), + LineData(time: .utc(timestamp: 1557316800), value: 231.04), + LineData(time: .utc(timestamp: 1557320400), value: 230.63), + LineData(time: .utc(timestamp: 1557324000), value: 230.83), + LineData(time: .utc(timestamp: 1557327600), value: 230), + LineData(time: .utc(timestamp: 1557471600), value: 228.8), + LineData(time: .utc(timestamp: 1557475200), value: 227.73), + LineData(time: .utc(timestamp: 1557478800), value: 227.73), + LineData(time: .utc(timestamp: 1557482400), value: 227.84), + LineData(time: .utc(timestamp: 1557486000), value: 228.2), + LineData(time: .utc(timestamp: 1557489600), value: 228.33), + LineData(time: .utc(timestamp: 1557493200), value: 228.6), + LineData(time: .utc(timestamp: 1557496800), value: 227.11), + LineData(time: .utc(timestamp: 1557500400), value: 227), + LineData(time: .utc(timestamp: 1557730800), value: 226.29), + LineData(time: .utc(timestamp: 1557734400), value: 227.04), + LineData(time: .utc(timestamp: 1557738000), value: 227.97), + LineData(time: .utc(timestamp: 1557741600), value: 227.85), + LineData(time: .utc(timestamp: 1557745200), value: 227.13), + LineData(time: .utc(timestamp: 1557748800), value: 225.64), + LineData(time: .utc(timestamp: 1557752400), value: 224.46), + LineData(time: .utc(timestamp: 1557756000), value: 225.22), + LineData(time: .utc(timestamp: 1557759600), value: 224.22), + LineData(time: .utc(timestamp: 1557817200), value: 225.9), + LineData(time: .utc(timestamp: 1557820800), value: 226.15), + LineData(time: .utc(timestamp: 1557824400), value: 227.9), + LineData(time: .utc(timestamp: 1557828000), value: 228.86), + LineData(time: .utc(timestamp: 1557831600), value: 228.83), + LineData(time: .utc(timestamp: 1557835200), value: 228.17), + LineData(time: .utc(timestamp: 1557838800), value: 228.71), + LineData(time: .utc(timestamp: 1557842400), value: 227.68), + LineData(time: .utc(timestamp: 1557846000), value: 227.88), + LineData(time: .utc(timestamp: 1557903600), value: 227.67), + LineData(time: .utc(timestamp: 1557907200), value: 227.52), + LineData(time: .utc(timestamp: 1557910800), value: 226.05), + LineData(time: .utc(timestamp: 1557914400), value: 224.54), + LineData(time: .utc(timestamp: 1557918000), value: 225.96), + LineData(time: .utc(timestamp: 1557921600), value: 224.88), + LineData(time: .utc(timestamp: 1557925200), value: 226.78), + LineData(time: .utc(timestamp: 1557928800), value: 229.09), + LineData(time: .utc(timestamp: 1557932400), value: 228.69), + LineData(time: .utc(timestamp: 1557990000), value: 230.22), + LineData(time: .utc(timestamp: 1557993600), value: 231.12), + LineData(time: .utc(timestamp: 1557997200), value: 229.67), + LineData(time: .utc(timestamp: 1558000800), value: 229.44), + LineData(time: .utc(timestamp: 1558004400), value: 229.72), + LineData(time: .utc(timestamp: 1558008000), value: 229.57), + LineData(time: .utc(timestamp: 1558011600), value: 229.42), + LineData(time: .utc(timestamp: 1558015200), value: 229.23), + LineData(time: .utc(timestamp: 1558018800), value: 228.19), + LineData(time: .utc(timestamp: 1558076400), value: 227.72), + LineData(time: .utc(timestamp: 1558080000), value: 227.31), + LineData(time: .utc(timestamp: 1558083600), value: 226.93), + LineData(time: .utc(timestamp: 1558087200), value: 227.15), + LineData(time: .utc(timestamp: 1558090800), value: 226.75), + LineData(time: .utc(timestamp: 1558094400), value: 226.5), + LineData(time: .utc(timestamp: 1558098000), value: 227.4), + LineData(time: .utc(timestamp: 1558101600), value: 227.96), + LineData(time: .utc(timestamp: 1558105200), value: 226.94), + LineData(time: .utc(timestamp: 1558335600), value: 227.64), + LineData(time: .utc(timestamp: 1558339200), value: 226.39), + LineData(time: .utc(timestamp: 1558342800), value: 226.03), + LineData(time: .utc(timestamp: 1558346400), value: 225.91), + LineData(time: .utc(timestamp: 1558350000), value: 226.21), + LineData(time: .utc(timestamp: 1558353600), value: 225.52), + LineData(time: .utc(timestamp: 1558357200), value: 225.71), + LineData(time: .utc(timestamp: 1558360800), value: 226.18), + LineData(time: .utc(timestamp: 1558364400), value: 226), + LineData(time: .utc(timestamp: 1558422000), value: 226.81), + LineData(time: .utc(timestamp: 1558425600), value: 226.52), + LineData(time: .utc(timestamp: 1558429200), value: 226.98), + LineData(time: .utc(timestamp: 1558432800), value: 229.19), + LineData(time: .utc(timestamp: 1558436400), value: 229.65), + LineData(time: .utc(timestamp: 1558440000), value: 229.8), + LineData(time: .utc(timestamp: 1558443600), value: 229.37), + LineData(time: .utc(timestamp: 1558447200), value: 231.13), + LineData(time: .utc(timestamp: 1558450800), value: 232.71), + LineData(time: .utc(timestamp: 1558508400), value: 231.06), + LineData(time: .utc(timestamp: 1558512000), value: 231.93), + LineData(time: .utc(timestamp: 1558515600), value: 236.04), + LineData(time: .utc(timestamp: 1558519200), value: 235.81), + LineData(time: .utc(timestamp: 1558522800), value: 237.09), + LineData(time: .utc(timestamp: 1558526400), value: 236.79), + LineData(time: .utc(timestamp: 1558530000), value: 236.6), + LineData(time: .utc(timestamp: 1558533600), value: 235.73), + LineData(time: .utc(timestamp: 1558537200), value: 235.86), + LineData(time: .utc(timestamp: 1558594800), value: 233.31), + LineData(time: .utc(timestamp: 1558598400), value: 232.46), + LineData(time: .utc(timestamp: 1558602000), value: 233.03), + LineData(time: .utc(timestamp: 1558605600), value: 233.2), + LineData(time: .utc(timestamp: 1558609200), value: 232.8), + LineData(time: .utc(timestamp: 1558612800), value: 231.67), + LineData(time: .utc(timestamp: 1558616400), value: 230.71), + LineData(time: .utc(timestamp: 1558620000), value: 229.05), + LineData(time: .utc(timestamp: 1558623600), value: 229.3), + LineData(time: .utc(timestamp: 1558681200), value: 234.3), + LineData(time: .utc(timestamp: 1558684800), value: 233.85), + LineData(time: .utc(timestamp: 1558688400), value: 233.68), + LineData(time: .utc(timestamp: 1558692000), value: 234.95), + LineData(time: .utc(timestamp: 1558695600), value: 235.34), + LineData(time: .utc(timestamp: 1558699200), value: 235.34), + LineData(time: .utc(timestamp: 1558702800), value: 234.76), + LineData(time: .utc(timestamp: 1558706400), value: 233.3), + LineData(time: .utc(timestamp: 1558710000), value: 234.45), + LineData(time: .utc(timestamp: 1558940400), value: 235.6), + LineData(time: .utc(timestamp: 1558944000), value: 235.7), + LineData(time: .utc(timestamp: 1558947600), value: 234.95), + LineData(time: .utc(timestamp: 1558951200), value: 235.03), + LineData(time: .utc(timestamp: 1558954800), value: 234.93), + LineData(time: .utc(timestamp: 1558958400), value: 234.33), + LineData(time: .utc(timestamp: 1558962000), value: 234.25), + LineData(time: .utc(timestamp: 1558965600), value: 234.98), + LineData(time: .utc(timestamp: 1558969200), value: 236), + LineData(time: .utc(timestamp: 1559026800), value: 236.11), + LineData(time: .utc(timestamp: 1559030400), value: 235.83), + LineData(time: .utc(timestamp: 1559034000), value: 235.98), + LineData(time: .utc(timestamp: 1559037600), value: 235.94), + LineData(time: .utc(timestamp: 1559041200), value: 236.36), + LineData(time: .utc(timestamp: 1559044800), value: 236.07), + LineData(time: .utc(timestamp: 1559048400), value: 235.69), + LineData(time: .utc(timestamp: 1559052000), value: 232.94), + LineData(time: .utc(timestamp: 1559055600), value: 233.79) + ] + series.setData(data: data) + self.series = series + } + +} diff --git a/ExampleSPM/LightweightCharts/Example/InvertedPriceScaleViewController.swift b/ExampleSPM/LightweightCharts/Example/InvertedPriceScaleViewController.swift new file mode 100644 index 0000000..4d0ac52 --- /dev/null +++ b/ExampleSPM/LightweightCharts/Example/InvertedPriceScaleViewController.swift @@ -0,0 +1,210 @@ +import UIKit +import LightweightCharts + +class InvertedPriceScaleViewController: UIViewController { + + private var chart: LightweightCharts! + private var series: LineSeries! + + override func viewDidLoad() { + super.viewDidLoad() + if #available(iOS 13.0, *) { + view.backgroundColor = .systemBackground + } else { + view.backgroundColor = .white + } + + setupUI() + setupData() + } + + private func setupUI() { + let options = ChartOptions( + rightPriceScale: VisiblePriceScaleOptions( + invertScale: true, + scaleMargins: PriceScaleMargins( + top: 0.1, + bottom: 0.1 + ) + ) + ) + let chart = LightweightCharts(options: options) + view.addSubview(chart) + chart.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + ]) + } else { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } + self.chart = chart + } + + private func setupData() { + let series = chart.addLineSeries(options: nil) + let data = [ + LineData(time: .string("2016-07-18"), value: 661.47), + LineData(time: .string("2016-07-25"), value: 623.83), + LineData(time: .string("2016-08-01"), value: 592.47), + LineData(time: .string("2016-08-08"), value: 568.76), + LineData(time: .string("2016-08-15"), value: 577.55), + LineData(time: .string("2016-08-22"), value: 573.20), + LineData(time: .string("2016-08-29"), value: 603.72), + LineData(time: .string("2016-09-05"), value: 606.32), + LineData(time: .string("2016-09-12"), value: 608.00), + LineData(time: .string("2016-09-19"), value: 598.98), + LineData(time: .string("2016-09-26"), value: 608.60), + LineData(time: .string("2016-10-03"), value: 613.06), + LineData(time: .string("2016-10-10"), value: 638.97), + LineData(time: .string("2016-10-17"), value: 648.74), + LineData(time: .string("2016-10-24"), value: 697.23), + LineData(time: .string("2016-10-31"), value: 709.93), + LineData(time: .string("2016-11-07"), value: 700.38), + LineData(time: .string("2016-11-14"), value: 727.09), + LineData(time: .string("2016-11-21"), value: 727.32), + LineData(time: .string("2016-11-28"), value: 762.00), + LineData(time: .string("2016-12-05"), value: 768.97), + LineData(time: .string("2016-12-12"), value: 788.67), + LineData(time: .string("2016-12-19"), value: 890.67), + LineData(time: .string("2016-12-26"), value: 997.75), + LineData(time: .string("2017-01-02"), value: 909.75), + LineData(time: .string("2017-01-09"), value: 821.86), + LineData(time: .string("2017-01-16"), value: 923.76), + LineData(time: .string("2017-01-23"), value: 912.01), + LineData(time: .string("2017-01-30"), value: 1011.07), + LineData(time: .string("2017-02-06"), value: 1000.73), + LineData(time: .string("2017-02-13"), value: 1051.80), + LineData(time: .string("2017-02-20"), value: 1179.05), + LineData(time: .string("2017-02-27"), value: 1273.00), + LineData(time: .string("2017-03-06"), value: 1226.62), + LineData(time: .string("2017-03-13"), value: 1017.97), + LineData(time: .string("2017-03-20"), value: 960.00), + LineData(time: .string("2017-03-27"), value: 1078.01), + LineData(time: .string("2017-04-03"), value: 1206.20), + LineData(time: .string("2017-04-10"), value: 1162.31), + LineData(time: .string("2017-04-17"), value: 1241.99), + LineData(time: .string("2017-04-24"), value: 1350.21), + LineData(time: .string("2017-05-01"), value: 1554.01), + LineData(time: .string("2017-05-08"), value: 1784.00), + LineData(time: .string("2017-05-15"), value: 2017.55), + LineData(time: .string("2017-05-22"), value: 2178.81), + LineData(time: .string("2017-05-29"), value: 2530.27), + LineData(time: .string("2017-06-05"), value: 2954.22), + LineData(time: .string("2017-06-12"), value: 2516.98), + LineData(time: .string("2017-06-19"), value: 2502.03), + LineData(time: .string("2017-06-26"), value: 2504.37), + LineData(time: .string("2017-07-03"), value: 2502.28), + LineData(time: .string("2017-07-10"), value: 1917.63), + LineData(time: .string("2017-07-17"), value: 2749.02), + LineData(time: .string("2017-07-24"), value: 2742.37), + LineData(time: .string("2017-07-31"), value: 3222.75), + LineData(time: .string("2017-08-07"), value: 4053.87), + LineData(time: .string("2017-08-14"), value: 4058.68), + LineData(time: .string("2017-08-21"), value: 4337.68), + LineData(time: .string("2017-08-28"), value: 4606.26), + LineData(time: .string("2017-09-04"), value: 4226.22), + LineData(time: .string("2017-09-11"), value: 3662.99), + LineData(time: .string("2017-09-18"), value: 3664.22), + LineData(time: .string("2017-09-25"), value: 4377.22), + LineData(time: .string("2017-10-02"), value: 4597.98), + LineData(time: .string("2017-10-09"), value: 5679.70), + LineData(time: .string("2017-10-16"), value: 5969.00), + LineData(time: .string("2017-10-23"), value: 6137.37), + LineData(time: .string("2017-10-30"), value: 7372.72), + LineData(time: .string("2017-11-06"), value: 5870.37), + LineData(time: .string("2017-11-13"), value: 8016.58), + LineData(time: .string("2017-11-20"), value: 9271.06), + LineData(time: .string("2017-11-27"), value: 11250.00), + LineData(time: .string("2017-12-04"), value: 14691.00), + LineData(time: .string("2017-12-11"), value: 18953.00), + LineData(time: .string("2017-12-18"), value: 14157.87), + LineData(time: .string("2017-12-25"), value: 13880.00), + LineData(time: .string("2018-01-01"), value: 16124.02), + LineData(time: .string("2018-01-08"), value: 13647.99), + LineData(time: .string("2018-01-15"), value: 11558.87), + LineData(time: .string("2018-01-22"), value: 11685.58), + LineData(time: .string("2018-01-29"), value: 8191.00), + LineData(time: .string("2018-02-05"), value: 8067.00), + LineData(time: .string("2018-02-12"), value: 10421.06), + LineData(time: .string("2018-02-19"), value: 9590.04), + LineData(time: .string("2018-02-26"), value: 11463.27), + LineData(time: .string("2018-03-05"), value: 9535.04), + LineData(time: .string("2018-03-12"), value: 8188.24), + LineData(time: .string("2018-03-19"), value: 8453.90), + LineData(time: .string("2018-03-26"), value: 6813.52), + LineData(time: .string("2018-04-02"), value: 7027.26), + LineData(time: .string("2018-04-09"), value: 8354.22), + LineData(time: .string("2018-04-16"), value: 8789.96), + LineData(time: .string("2018-04-23"), value: 9393.99), + LineData(time: .string("2018-04-30"), value: 9623.54), + LineData(time: .string("2018-05-07"), value: 8696.58), + LineData(time: .string("2018-05-14"), value: 8518.48), + LineData(time: .string("2018-05-21"), value: 7347.39), + LineData(time: .string("2018-05-28"), value: 7703.67), + LineData(time: .string("2018-06-04"), value: 6781.17), + LineData(time: .string("2018-06-11"), value: 6453.41), + LineData(time: .string("2018-06-18"), value: 6153.40), + LineData(time: .string("2018-06-25"), value: 6349.99), + LineData(time: .string("2018-07-02"), value: 6706.60), + LineData(time: .string("2018-07-09"), value: 6349.30), + LineData(time: .string("2018-07-16"), value: 7396.60), + LineData(time: .string("2018-07-23"), value: 8216.74), + LineData(time: .string("2018-07-30"), value: 7032.61), + LineData(time: .string("2018-08-06"), value: 6310.82), + LineData(time: .string("2018-08-13"), value: 6481.99), + LineData(time: .string("2018-08-20"), value: 6700.46), + LineData(time: .string("2018-08-27"), value: 7290.31), + LineData(time: .string("2018-09-03"), value: 6236.04), + LineData(time: .string("2018-09-10"), value: 6499.98), + LineData(time: .string("2018-09-17"), value: 6702.22), + LineData(time: .string("2018-09-24"), value: 6597.81), + LineData(time: .string("2018-10-01"), value: 6577.63), + LineData(time: .string("2018-10-08"), value: 6183.00), + LineData(time: .string("2018-10-15"), value: 6413.38), + LineData(time: .string("2018-10-22"), value: 6405.57), + LineData(time: .string("2018-10-29"), value: 6421.76), + LineData(time: .string("2018-11-05"), value: 6357.54), + LineData(time: .string("2018-11-12"), value: 5559.26), + LineData(time: .string("2018-11-19"), value: 3938.89), + LineData(time: .string("2018-11-26"), value: 4102.05), + LineData(time: .string("2018-12-03"), value: 3529.75), + LineData(time: .string("2018-12-10"), value: 3193.78), + LineData(time: .string("2018-12-17"), value: 3943.83), + LineData(time: .string("2018-12-24"), value: 3835.79), + LineData(time: .string("2018-12-31"), value: 4040.71), + LineData(time: .string("2019-01-07"), value: 3515.95), + LineData(time: .string("2019-01-14"), value: 3536.72), + LineData(time: .string("2019-01-21"), value: 3533.23), + LineData(time: .string("2019-01-28"), value: 3414.82), + LineData(time: .string("2019-02-04"), value: 3650.37), + LineData(time: .string("2019-02-11"), value: 3625.60), + LineData(time: .string("2019-02-18"), value: 3730.68), + LineData(time: .string("2019-02-25"), value: 3789.52), + LineData(time: .string("2019-03-04"), value: 3897.92), + LineData(time: .string("2019-03-11"), value: 3965.50), + LineData(time: .string("2019-03-18"), value: 3969.99), + LineData(time: .string("2019-03-25"), value: 4096.08), + LineData(time: .string("2019-04-01"), value: 5190.85), + LineData(time: .string("2019-04-08"), value: 5162.72), + LineData(time: .string("2019-04-15"), value: 5295.65), + LineData(time: .string("2019-04-22"), value: 5160.98), + LineData(time: .string("2019-04-29"), value: 5709.32), + LineData(time: .string("2019-05-06"), value: 6974.35), + LineData(time: .string("2019-05-13"), value: 8200.00), + LineData(time: .string("2019-05-20"), value: 8733.26), + LineData(time: .string("2019-05-27"), value: 8702.43) + ] + series.setData(data: data) + self.series = series + } + +} diff --git a/ExampleSPM/LightweightCharts/Example/LegendViewController.swift b/ExampleSPM/LightweightCharts/Example/LegendViewController.swift new file mode 100644 index 0000000..cbdc6e7 --- /dev/null +++ b/ExampleSPM/LightweightCharts/Example/LegendViewController.swift @@ -0,0 +1,268 @@ +import UIKit +import LightweightCharts + +class LegendViewController: UIViewController { + + private var chart: LightweightCharts! + private var series: AreaSeries! + private let legendLabel = UILabel() + private let legend = "ETC USD 7D VWAP" + + override func viewDidLoad() { + super.viewDidLoad() + if #available(iOS 13.0, *) { + view.backgroundColor = .systemBackground + } else { + view.backgroundColor = .white + } + + setupUI() + setupData() + setupSubscription() + } + + private func setupUI() { + let padding: CGFloat = 16 + legendLabel.text = legend + legendLabel.font = .systemFont(ofSize: 18) + view.addSubview(legendLabel) + legendLabel.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + legendLabel.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: padding), + legendLabel.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -padding), + legendLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: padding) + ]) + } else { + NSLayoutConstraint.activate([ + legendLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: padding), + legendLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -padding), + legendLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: padding) + ]) + } + + let options = ChartOptions( + layout: LayoutOptions(backgroundColor: "#000000", textColor: "#d1d4dc"), + rightPriceScale: VisiblePriceScaleOptions(scaleMargins: PriceScaleMargins(top: 0.3, bottom: 0.25)), + crosshair: CrosshairOptions( + vertLine: CrosshairLineOptions(color: "rgba(224, 227, 235, 0.1)", width: .four, style: .solid), + horzLine: CrosshairLineOptions(visible: false, labelVisible: false) + ), + grid: GridOptions( + verticalLines: GridLineOptions(color: "rgba(42, 46, 57, 0)"), + horizontalLines: GridLineOptions(color: "rgba(42, 46, 57, 0)") + ) + ) + let chart = LightweightCharts(options: options) + view.addSubview(chart) + chart.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + chart.topAnchor.constraint(equalTo: legendLabel.bottomAnchor, constant: padding), + chart.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + ]) + } else { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.trailingAnchor), + chart.topAnchor.constraint(equalTo: legendLabel.bottomAnchor, constant: padding), + chart.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } + self.chart = chart + } + + private func setupData() { + let options = AreaSeriesOptions( + topColor: "rgba(38, 198, 218, 0.56)", + bottomColor: "rgba(38, 198, 218, 0.04)", + lineColor: "rgba(38, 198, 218, 1)", + lineWidth: .two, + crosshairMarkerVisible: false + ) + let series = chart.addAreaSeries(options: options) + let data = [ + LineData(time: .string("2018-10-19"), value: 26.19), + LineData(time: .string("2018-10-22"), value: 25.87), + LineData(time: .string("2018-10-23"), value: 25.83), + LineData(time: .string("2018-10-24"), value: 25.78), + LineData(time: .string("2018-10-25"), value: 25.82), + LineData(time: .string("2018-10-26"), value: 25.81), + LineData(time: .string("2018-10-29"), value: 25.82), + LineData(time: .string("2018-10-30"), value: 25.71), + LineData(time: .string("2018-10-31"), value: 25.82), + LineData(time: .string("2018-11-01"), value: 25.72), + LineData(time: .string("2018-11-02"), value: 25.74), + LineData(time: .string("2018-11-05"), value: 25.81), + LineData(time: .string("2018-11-06"), value: 25.75), + LineData(time: .string("2018-11-07"), value: 25.73), + LineData(time: .string("2018-11-08"), value: 25.75), + LineData(time: .string("2018-11-09"), value: 25.75), + LineData(time: .string("2018-11-12"), value: 25.76), + LineData(time: .string("2018-11-13"), value: 25.80), + LineData(time: .string("2018-11-14"), value: 25.77), + LineData(time: .string("2018-11-15"), value: 25.75), + LineData(time: .string("2018-11-16"), value: 25.75), + LineData(time: .string("2018-11-19"), value: 25.75), + LineData(time: .string("2018-11-20"), value: 25.72), + LineData(time: .string("2018-11-21"), value: 25.78), + LineData(time: .string("2018-11-23"), value: 25.72), + LineData(time: .string("2018-11-26"), value: 25.78), + LineData(time: .string("2018-11-27"), value: 25.85), + LineData(time: .string("2018-11-28"), value: 25.85), + LineData(time: .string("2018-11-29"), value: 25.55), + LineData(time: .string("2018-11-30"), value: 25.41), + LineData(time: .string("2018-12-03"), value: 25.41), + LineData(time: .string("2018-12-04"), value: 25.42), + LineData(time: .string("2018-12-06"), value: 25.33), + LineData(time: .string("2018-12-07"), value: 25.39), + LineData(time: .string("2018-12-10"), value: 25.32), + LineData(time: .string("2018-12-11"), value: 25.48), + LineData(time: .string("2018-12-12"), value: 25.39), + LineData(time: .string("2018-12-13"), value: 25.45), + LineData(time: .string("2018-12-14"), value: 25.52), + LineData(time: .string("2018-12-17"), value: 25.38), + LineData(time: .string("2018-12-18"), value: 25.36), + LineData(time: .string("2018-12-19"), value: 25.65), + LineData(time: .string("2018-12-20"), value: 25.70), + LineData(time: .string("2018-12-21"), value: 25.66), + LineData(time: .string("2018-12-24"), value: 25.66), + LineData(time: .string("2018-12-26"), value: 25.65), + LineData(time: .string("2018-12-27"), value: 25.66), + LineData(time: .string("2018-12-28"), value: 25.68), + LineData(time: .string("2018-12-31"), value: 25.77), + LineData(time: .string("2019-01-02"), value: 25.72), + LineData(time: .string("2019-01-03"), value: 25.69), + LineData(time: .string("2019-01-04"), value: 25.71), + LineData(time: .string("2019-01-07"), value: 25.72), + LineData(time: .string("2019-01-08"), value: 25.72), + LineData(time: .string("2019-01-09"), value: 25.66), + LineData(time: .string("2019-01-10"), value: 25.85), + LineData(time: .string("2019-01-11"), value: 25.92), + LineData(time: .string("2019-01-14"), value: 25.94), + LineData(time: .string("2019-01-15"), value: 25.95), + LineData(time: .string("2019-01-16"), value: 26.00), + LineData(time: .string("2019-01-17"), value: 25.99), + LineData(time: .string("2019-01-18"), value: 25.60), + LineData(time: .string("2019-01-22"), value: 25.81), + LineData(time: .string("2019-01-23"), value: 25.70), + LineData(time: .string("2019-01-24"), value: 25.74), + LineData(time: .string("2019-01-25"), value: 25.80), + LineData(time: .string("2019-01-28"), value: 25.83), + LineData(time: .string("2019-01-29"), value: 25.70), + LineData(time: .string("2019-01-30"), value: 25.78), + LineData(time: .string("2019-01-31"), value: 25.35), + LineData(time: .string("2019-02-01"), value: 25.60), + LineData(time: .string("2019-02-04"), value: 25.65), + LineData(time: .string("2019-02-05"), value: 25.73), + LineData(time: .string("2019-02-06"), value: 25.71), + LineData(time: .string("2019-02-07"), value: 25.71), + LineData(time: .string("2019-02-08"), value: 25.72), + LineData(time: .string("2019-02-11"), value: 25.76), + LineData(time: .string("2019-02-12"), value: 25.84), + LineData(time: .string("2019-02-13"), value: 25.85), + LineData(time: .string("2019-02-14"), value: 25.87), + LineData(time: .string("2019-02-15"), value: 25.89), + LineData(time: .string("2019-02-19"), value: 25.90), + LineData(time: .string("2019-02-20"), value: 25.92), + LineData(time: .string("2019-02-21"), value: 25.96), + LineData(time: .string("2019-02-22"), value: 26.00), + LineData(time: .string("2019-02-25"), value: 25.93), + LineData(time: .string("2019-02-26"), value: 25.92), + LineData(time: .string("2019-02-27"), value: 25.67), + LineData(time: .string("2019-02-28"), value: 25.79), + LineData(time: .string("2019-03-01"), value: 25.86), + LineData(time: .string("2019-03-04"), value: 25.94), + LineData(time: .string("2019-03-05"), value: 26.02), + LineData(time: .string("2019-03-06"), value: 25.95), + LineData(time: .string("2019-03-07"), value: 25.89), + LineData(time: .string("2019-03-08"), value: 25.94), + LineData(time: .string("2019-03-11"), value: 25.91), + LineData(time: .string("2019-03-12"), value: 25.92), + LineData(time: .string("2019-03-13"), value: 26.00), + LineData(time: .string("2019-03-14"), value: 26.05), + LineData(time: .string("2019-03-15"), value: 26.11), + LineData(time: .string("2019-03-18"), value: 26.10), + LineData(time: .string("2019-03-19"), value: 25.98), + LineData(time: .string("2019-03-20"), value: 26.11), + LineData(time: .string("2019-03-21"), value: 26.12), + LineData(time: .string("2019-03-22"), value: 25.88), + LineData(time: .string("2019-03-25"), value: 25.85), + LineData(time: .string("2019-03-26"), value: 25.72), + LineData(time: .string("2019-03-27"), value: 25.73), + LineData(time: .string("2019-03-28"), value: 25.80), + LineData(time: .string("2019-03-29"), value: 25.77), + LineData(time: .string("2019-04-01"), value: 26.06), + LineData(time: .string("2019-04-02"), value: 25.93), + LineData(time: .string("2019-04-03"), value: 25.95), + LineData(time: .string("2019-04-04"), value: 26.06), + LineData(time: .string("2019-04-05"), value: 26.16), + LineData(time: .string("2019-04-08"), value: 26.12), + LineData(time: .string("2019-04-09"), value: 26.07), + LineData(time: .string("2019-04-10"), value: 26.13), + LineData(time: .string("2019-04-11"), value: 26.04), + LineData(time: .string("2019-04-12"), value: 26.04), + LineData(time: .string("2019-04-15"), value: 26.05), + LineData(time: .string("2019-04-16"), value: 26.01), + LineData(time: .string("2019-04-17"), value: 26.09), + LineData(time: .string("2019-04-18"), value: 26.00), + LineData(time: .string("2019-04-22"), value: 26.00), + LineData(time: .string("2019-04-23"), value: 26.06), + LineData(time: .string("2019-04-24"), value: 26.00), + LineData(time: .string("2019-04-25"), value: 25.81), + LineData(time: .string("2019-04-26"), value: 25.88), + LineData(time: .string("2019-04-29"), value: 25.91), + LineData(time: .string("2019-04-30"), value: 25.90), + LineData(time: .string("2019-05-01"), value: 26.02), + LineData(time: .string("2019-05-02"), value: 25.97), + LineData(time: .string("2019-05-03"), value: 26.02), + LineData(time: .string("2019-05-06"), value: 26.03), + LineData(time: .string("2019-05-07"), value: 26.04), + LineData(time: .string("2019-05-08"), value: 26.05), + LineData(time: .string("2019-05-09"), value: 26.05), + LineData(time: .string("2019-05-10"), value: 26.08), + LineData(time: .string("2019-05-13"), value: 26.05), + LineData(time: .string("2019-05-14"), value: 26.01), + LineData(time: .string("2019-05-15"), value: 26.03), + LineData(time: .string("2019-05-16"), value: 26.14), + LineData(time: .string("2019-05-17"), value: 26.09), + LineData(time: .string("2019-05-20"), value: 26.01), + LineData(time: .string("2019-05-21"), value: 26.12), + LineData(time: .string("2019-05-22"), value: 26.15), + LineData(time: .string("2019-05-23"), value: 26.18), + LineData(time: .string("2019-05-24"), value: 26.16), + LineData(time: .string("2019-05-28"), value: 26.23) + ] + series.setData(data: data) + self.series = series + } + + private func setupSubscription() { + chart.delegate = self + chart.subscribeCrosshairMove() + } + +} + +// MARK: - ChartDelegate +extension LegendViewController: ChartDelegate { + + func didClick(onChart chart: ChartApi, parameters: MouseEventParams) { + + } + + func didCrosshairMove(onChart chart: ChartApi, parameters: MouseEventParams) { + if case let .barPrice(price) = parameters.price(forSeries: series) { + self.legendLabel.text = self.legend + " \((price * 100).rounded() / 100)" + } else { + self.legendLabel.text = self.legend + } + } + + func didVisibleTimeRangeChange(onChart chart: ChartApi, parameters: TimeRange?) { + + } + +} diff --git a/ExampleSPM/LightweightCharts/Example/LogarithmicPriceScaleViewController.swift b/ExampleSPM/LightweightCharts/Example/LogarithmicPriceScaleViewController.swift new file mode 100644 index 0000000..60dcb68 --- /dev/null +++ b/ExampleSPM/LightweightCharts/Example/LogarithmicPriceScaleViewController.swift @@ -0,0 +1,211 @@ +import UIKit +import LightweightCharts + +class LogarithmicPriceScaleViewController: UIViewController { + + private var chart: LightweightCharts! + private var series: LineSeries! + + override func viewDidLoad() { + super.viewDidLoad() + if #available(iOS 13.0, *) { + view.backgroundColor = .systemBackground + } else { + view.backgroundColor = .white + } + + setupUI() + setupData() + } + + private func setupUI() { + let options = ChartOptions( + rightPriceScale: VisiblePriceScaleOptions( + mode: .logarithmic, + scaleMargins: PriceScaleMargins( + top: 0.1, + bottom: 0.1 + ) + ) + ) + let chart = LightweightCharts(options: options) + view.addSubview(chart) + chart.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + ]) + } else { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } + self.chart = chart + } + + private func setupData() { + let options = LineSeriesOptions(color: "rgba(38, 198, 218, 1)", lineWidth: .three) + let series = chart.addLineSeries(options: options) + let data = [ + LineData(time: .string("2016-07-18"), value: 661.47), + LineData(time: .string("2016-07-25"), value: 623.83), + LineData(time: .string("2016-08-01"), value: 592.47), + LineData(time: .string("2016-08-08"), value: 568.76), + LineData(time: .string("2016-08-15"), value: 577.55), + LineData(time: .string("2016-08-22"), value: 573.20), + LineData(time: .string("2016-08-29"), value: 603.72), + LineData(time: .string("2016-09-05"), value: 606.32), + LineData(time: .string("2016-09-12"), value: 608.00), + LineData(time: .string("2016-09-19"), value: 598.98), + LineData(time: .string("2016-09-26"), value: 608.60), + LineData(time: .string("2016-10-03"), value: 613.06), + LineData(time: .string("2016-10-10"), value: 638.97), + LineData(time: .string("2016-10-17"), value: 648.74), + LineData(time: .string("2016-10-24"), value: 697.23), + LineData(time: .string("2016-10-31"), value: 709.93), + LineData(time: .string("2016-11-07"), value: 700.38), + LineData(time: .string("2016-11-14"), value: 727.09), + LineData(time: .string("2016-11-21"), value: 727.32), + LineData(time: .string("2016-11-28"), value: 762.00), + LineData(time: .string("2016-12-05"), value: 768.97), + LineData(time: .string("2016-12-12"), value: 788.67), + LineData(time: .string("2016-12-19"), value: 890.67), + LineData(time: .string("2016-12-26"), value: 997.75), + LineData(time: .string("2017-01-02"), value: 909.75), + LineData(time: .string("2017-01-09"), value: 821.86), + LineData(time: .string("2017-01-16"), value: 923.76), + LineData(time: .string("2017-01-23"), value: 912.01), + LineData(time: .string("2017-01-30"), value: 1011.07), + LineData(time: .string("2017-02-06"), value: 1000.73), + LineData(time: .string("2017-02-13"), value: 1051.80), + LineData(time: .string("2017-02-20"), value: 1179.05), + LineData(time: .string("2017-02-27"), value: 1273.00), + LineData(time: .string("2017-03-06"), value: 1226.62), + LineData(time: .string("2017-03-13"), value: 1017.97), + LineData(time: .string("2017-03-20"), value: 960.00), + LineData(time: .string("2017-03-27"), value: 1078.01), + LineData(time: .string("2017-04-03"), value: 1206.20), + LineData(time: .string("2017-04-10"), value: 1162.31), + LineData(time: .string("2017-04-17"), value: 1241.99), + LineData(time: .string("2017-04-24"), value: 1350.21), + LineData(time: .string("2017-05-01"), value: 1554.01), + LineData(time: .string("2017-05-08"), value: 1784.00), + LineData(time: .string("2017-05-15"), value: 2017.55), + LineData(time: .string("2017-05-22"), value: 2178.81), + LineData(time: .string("2017-05-29"), value: 2530.27), + LineData(time: .string("2017-06-05"), value: 2954.22), + LineData(time: .string("2017-06-12"), value: 2516.98), + LineData(time: .string("2017-06-19"), value: 2502.03), + LineData(time: .string("2017-06-26"), value: 2504.37), + LineData(time: .string("2017-07-03"), value: 2502.28), + LineData(time: .string("2017-07-10"), value: 1917.63), + LineData(time: .string("2017-07-17"), value: 2749.02), + LineData(time: .string("2017-07-24"), value: 2742.37), + LineData(time: .string("2017-07-31"), value: 3222.75), + LineData(time: .string("2017-08-07"), value: 4053.87), + LineData(time: .string("2017-08-14"), value: 4058.68), + LineData(time: .string("2017-08-21"), value: 4337.68), + LineData(time: .string("2017-08-28"), value: 4606.26), + LineData(time: .string("2017-09-04"), value: 4226.22), + LineData(time: .string("2017-09-11"), value: 3662.99), + LineData(time: .string("2017-09-18"), value: 3664.22), + LineData(time: .string("2017-09-25"), value: 4377.22), + LineData(time: .string("2017-10-02"), value: 4597.98), + LineData(time: .string("2017-10-09"), value: 5679.70), + LineData(time: .string("2017-10-16"), value: 5969.00), + LineData(time: .string("2017-10-23"), value: 6137.37), + LineData(time: .string("2017-10-30"), value: 7372.72), + LineData(time: .string("2017-11-06"), value: 5870.37), + LineData(time: .string("2017-11-13"), value: 8016.58), + LineData(time: .string("2017-11-20"), value: 9271.06), + LineData(time: .string("2017-11-27"), value: 11250.00), + LineData(time: .string("2017-12-04"), value: 14691.00), + LineData(time: .string("2017-12-11"), value: 18953.00), + LineData(time: .string("2017-12-18"), value: 14157.87), + LineData(time: .string("2017-12-25"), value: 13880.00), + LineData(time: .string("2018-01-01"), value: 16124.02), + LineData(time: .string("2018-01-08"), value: 13647.99), + LineData(time: .string("2018-01-15"), value: 11558.87), + LineData(time: .string("2018-01-22"), value: 11685.58), + LineData(time: .string("2018-01-29"), value: 8191.00), + LineData(time: .string("2018-02-05"), value: 8067.00), + LineData(time: .string("2018-02-12"), value: 10421.06), + LineData(time: .string("2018-02-19"), value: 9590.04), + LineData(time: .string("2018-02-26"), value: 11463.27), + LineData(time: .string("2018-03-05"), value: 9535.04), + LineData(time: .string("2018-03-12"), value: 8188.24), + LineData(time: .string("2018-03-19"), value: 8453.90), + LineData(time: .string("2018-03-26"), value: 6813.52), + LineData(time: .string("2018-04-02"), value: 7027.26), + LineData(time: .string("2018-04-09"), value: 8354.22), + LineData(time: .string("2018-04-16"), value: 8789.96), + LineData(time: .string("2018-04-23"), value: 9393.99), + LineData(time: .string("2018-04-30"), value: 9623.54), + LineData(time: .string("2018-05-07"), value: 8696.58), + LineData(time: .string("2018-05-14"), value: 8518.48), + LineData(time: .string("2018-05-21"), value: 7347.39), + LineData(time: .string("2018-05-28"), value: 7703.67), + LineData(time: .string("2018-06-04"), value: 6781.17), + LineData(time: .string("2018-06-11"), value: 6453.41), + LineData(time: .string("2018-06-18"), value: 6153.40), + LineData(time: .string("2018-06-25"), value: 6349.99), + LineData(time: .string("2018-07-02"), value: 6706.60), + LineData(time: .string("2018-07-09"), value: 6349.30), + LineData(time: .string("2018-07-16"), value: 7396.60), + LineData(time: .string("2018-07-23"), value: 8216.74), + LineData(time: .string("2018-07-30"), value: 7032.61), + LineData(time: .string("2018-08-06"), value: 6310.82), + LineData(time: .string("2018-08-13"), value: 6481.99), + LineData(time: .string("2018-08-20"), value: 6700.46), + LineData(time: .string("2018-08-27"), value: 7290.31), + LineData(time: .string("2018-09-03"), value: 6236.04), + LineData(time: .string("2018-09-10"), value: 6499.98), + LineData(time: .string("2018-09-17"), value: 6702.22), + LineData(time: .string("2018-09-24"), value: 6597.81), + LineData(time: .string("2018-10-01"), value: 6577.63), + LineData(time: .string("2018-10-08"), value: 6183.00), + LineData(time: .string("2018-10-15"), value: 6413.38), + LineData(time: .string("2018-10-22"), value: 6405.57), + LineData(time: .string("2018-10-29"), value: 6421.76), + LineData(time: .string("2018-11-05"), value: 6357.54), + LineData(time: .string("2018-11-12"), value: 5559.26), + LineData(time: .string("2018-11-19"), value: 3938.89), + LineData(time: .string("2018-11-26"), value: 4102.05), + LineData(time: .string("2018-12-03"), value: 3529.75), + LineData(time: .string("2018-12-10"), value: 3193.78), + LineData(time: .string("2018-12-17"), value: 3943.83), + LineData(time: .string("2018-12-24"), value: 3835.79), + LineData(time: .string("2018-12-31"), value: 4040.71), + LineData(time: .string("2019-01-07"), value: 3515.95), + LineData(time: .string("2019-01-14"), value: 3536.72), + LineData(time: .string("2019-01-21"), value: 3533.23), + LineData(time: .string("2019-01-28"), value: 3414.82), + LineData(time: .string("2019-02-04"), value: 3650.37), + LineData(time: .string("2019-02-11"), value: 3625.60), + LineData(time: .string("2019-02-18"), value: 3730.68), + LineData(time: .string("2019-02-25"), value: 3789.52), + LineData(time: .string("2019-03-04"), value: 3897.92), + LineData(time: .string("2019-03-11"), value: 3965.50), + LineData(time: .string("2019-03-18"), value: 3969.99), + LineData(time: .string("2019-03-25"), value: 4096.08), + LineData(time: .string("2019-04-01"), value: 5190.85), + LineData(time: .string("2019-04-08"), value: 5162.72), + LineData(time: .string("2019-04-15"), value: 5295.65), + LineData(time: .string("2019-04-22"), value: 5160.98), + LineData(time: .string("2019-04-29"), value: 5709.32), + LineData(time: .string("2019-05-06"), value: 6974.35), + LineData(time: .string("2019-05-13"), value: 8200.00), + LineData(time: .string("2019-05-20"), value: 8733.26), + LineData(time: .string("2019-05-27"), value: 8702.43) + ] + series.setData(data: data) + self.series = series + } + +} diff --git a/ExampleSPM/LightweightCharts/Example/MagnifierTooltipViewController.swift b/ExampleSPM/LightweightCharts/Example/MagnifierTooltipViewController.swift new file mode 100644 index 0000000..7608cba --- /dev/null +++ b/ExampleSPM/LightweightCharts/Example/MagnifierTooltipViewController.swift @@ -0,0 +1,448 @@ +import UIKit +import LightweightCharts + +class MagnifierTooltipViewController: UIViewController { + + private var chart: LightweightCharts! + private var series: AreaSeries! + private let tooltipView = TooltipView(accentColor: UIColor(red: 0, green: 120/255.0, blue: 1, alpha: 0.9)) + private let legend = "⬤ AERO" + + private var leadingConstraint: NSLayoutConstraint! + + override func viewDidLoad() { + super.viewDidLoad() + if #available(iOS 13.0, *) { + view.backgroundColor = .systemBackground + } else { + view.backgroundColor = .white + } + + setupUI() + setupData() + setupSubscription() + } + + private func setupUI() { + let options = ChartOptions( + leftPriceScale: VisiblePriceScaleOptions( + scaleMargins: PriceScaleMargins(top: 0.2, bottom: 0.2), + borderVisible: false + ), + timeScale: TimeScaleOptions(borderVisible: false), + crosshair: CrosshairOptions( + vertLine: CrosshairLineOptions( + color: "rgba(32, 38, 46, 0.1)", + width: .two, + style: .solid, + visible: true, + labelVisible: false + ), + horzLine: CrosshairLineOptions(visible: false, labelVisible: false) + ), + grid: GridOptions( + verticalLines: GridLineOptions(color: "#ffffff"), + horizontalLines: GridLineOptions(color: "#eee") + ) + ) + let chart = LightweightCharts(options: options) + view.addSubview(chart) + chart.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + ]) + } else { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } + self.chart = chart + + let shadowRadius: CGFloat = 4 + tooltipView.backgroundColor = .clear + tooltipView.layer.borderWidth = 1 + tooltipView.layer.shadowRadius = shadowRadius + tooltipView.layer.shadowOpacity = 0.75 + tooltipView.layer.shadowColor = UIColor.black.cgColor + tooltipView.layer.shadowOffset = .zero + view.addSubview(tooltipView) + tooltipView.translatesAutoresizingMaskIntoConstraints = false + leadingConstraint = tooltipView.leadingAnchor.constraint(equalTo: chart.leadingAnchor) + NSLayoutConstraint.activate([ + tooltipView.topAnchor.constraint(equalTo: chart.topAnchor, constant: shadowRadius), + tooltipView.bottomAnchor.constraint(equalTo: chart.bottomAnchor, constant: -shadowRadius), + tooltipView.widthAnchor.constraint(equalToConstant: 128), + leadingConstraint + ]) + + tooltipView.isHidden = true + + view.bringSubviewToFront(tooltipView) + } + + private func setupData() { + let options = AreaSeriesOptions( + topColor: "rgba(0, 120, 255, 0.2)", + bottomColor: "rgba(0, 120, 255, 0.0)", + lineColor: "rgba(0, 120, 255, 1)", + lineWidth: .three + ) + let series = chart.addAreaSeries(options: options) + let data = [ + LineData(time: .string("2018-03-28"), value: 154), + LineData(time: .string("2018-03-29"), value: 154.2), + LineData(time: .string("2018-03-30"), value: 155.60001), + LineData(time: .string("2018-04-02"), value: 156.25), + LineData(time: .string("2018-04-03"), value: 156.25), + LineData(time: .string("2018-04-04"), value: 156.05), + LineData(time: .string("2018-04-05"), value: 158.05), + LineData(time: .string("2018-04-06"), value: 157.3), + LineData(time: .string("2018-04-09"), value: 144), + LineData(time: .string("2018-04-10"), value: 144.8), + LineData(time: .string("2018-04-11"), value: 143.5), + LineData(time: .string("2018-04-12"), value: 147.05), + LineData(time: .string("2018-04-13"), value: 144.85001), + LineData(time: .string("2018-04-16"), value: 145.39999), + LineData(time: .string("2018-04-17"), value: 147.3), + LineData(time: .string("2018-04-18"), value: 153.55), + LineData(time: .string("2018-04-19"), value: 150.95), + LineData(time: .string("2018-04-20"), value: 149.39999), + LineData(time: .string("2018-04-23"), value: 148.5), + LineData(time: .string("2018-04-24"), value: 146.60001), + LineData(time: .string("2018-04-25"), value: 144.45), + LineData(time: .string("2018-04-26"), value: 145.60001), + LineData(time: .string("2018-04-27"), value: 144.3), + LineData(time: .string("2018-04-30"), value: 144), + LineData(time: .string("2018-05-02"), value: 147.3), + LineData(time: .string("2018-05-03"), value: 144.2), + LineData(time: .string("2018-05-04"), value: 141.64999), + LineData(time: .string("2018-05-07"), value: 141.89999), + LineData(time: .string("2018-05-08"), value: 140.39999), + LineData(time: .string("2018-05-10"), value: 139.8), + LineData(time: .string("2018-05-11"), value: 137.5), + LineData(time: .string("2018-05-14"), value: 136.14999), + LineData(time: .string("2018-05-15"), value: 138), + LineData(time: .string("2018-05-16"), value: 137.95), + LineData(time: .string("2018-05-17"), value: 137.95), + LineData(time: .string("2018-05-18"), value: 136.75), + LineData(time: .string("2018-05-21"), value: 136.2), + LineData(time: .string("2018-05-22"), value: 135), + LineData(time: .string("2018-05-23"), value: 132.55), + LineData(time: .string("2018-05-24"), value: 132.7), + LineData(time: .string("2018-05-25"), value: 132.2), + LineData(time: .string("2018-05-28"), value: 131.55), + LineData(time: .string("2018-05-29"), value: 131.85001), + LineData(time: .string("2018-05-30"), value: 139.85001), + LineData(time: .string("2018-05-31"), value: 140.8), + LineData(time: .string("2018-06-01"), value: 139.64999), + LineData(time: .string("2018-06-04"), value: 137.10001), + LineData(time: .string("2018-06-05"), value: 139.25), + LineData(time: .string("2018-06-06"), value: 141.3), + LineData(time: .string("2018-06-07"), value: 145), + LineData(time: .string("2018-06-08"), value: 143.89999), + LineData(time: .string("2018-06-11"), value: 142.7), + LineData(time: .string("2018-06-13"), value: 144.05), + LineData(time: .string("2018-06-14"), value: 143.55), + LineData(time: .string("2018-06-15"), value: 140.5), + LineData(time: .string("2018-06-18"), value: 139.64999), + LineData(time: .string("2018-06-19"), value: 138), + LineData(time: .string("2018-06-20"), value: 141), + LineData(time: .string("2018-06-21"), value: 140.55), + LineData(time: .string("2018-06-22"), value: 140.55), + LineData(time: .string("2018-06-25"), value: 140.75), + LineData(time: .string("2018-06-26"), value: 140.64999), + LineData(time: .string("2018-06-27"), value: 141.14999), + LineData(time: .string("2018-06-28"), value: 139.8), + LineData(time: .string("2018-06-29"), value: 139.8), + LineData(time: .string("2018-07-02"), value: 140.14999), + LineData(time: .string("2018-07-03"), value: 143.05), + LineData(time: .string("2018-07-04"), value: 140), + LineData(time: .string("2018-07-05"), value: 129.2), + LineData(time: .string("2018-07-06"), value: 129.55), + LineData(time: .string("2018-07-09"), value: 128.3), + LineData(time: .string("2018-07-10"), value: 126.55), + LineData(time: .string("2018-07-11"), value: 124.3), + LineData(time: .string("2018-07-12"), value: 124.8), + LineData(time: .string("2018-07-13"), value: 123.25), + LineData(time: .string("2018-07-16"), value: 123), + LineData(time: .string("2018-07-17"), value: 124.25), + LineData(time: .string("2018-07-18"), value: 123), + LineData(time: .string("2018-07-19"), value: 121), + LineData(time: .string("2018-07-20"), value: 121.45), + LineData(time: .string("2018-07-23"), value: 123.8), + LineData(time: .string("2018-07-24"), value: 122.15), + LineData(time: .string("2018-07-25"), value: 121.3), + LineData(time: .string("2018-07-26"), value: 122.7), + LineData(time: .string("2018-07-27"), value: 122.2), + LineData(time: .string("2018-07-30"), value: 121.7), + LineData(time: .string("2018-07-31"), value: 122.95), + LineData(time: .string("2018-08-01"), value: 121), + LineData(time: .string("2018-08-02"), value: 116), + LineData(time: .string("2018-08-03"), value: 118.1), + LineData(time: .string("2018-08-06"), value: 114.3), + LineData(time: .string("2018-08-07"), value: 114.25), + LineData(time: .string("2018-08-08"), value: 111.85), + LineData(time: .string("2018-08-09"), value: 109.7), + LineData(time: .string("2018-08-10"), value: 105), + LineData(time: .string("2018-08-13"), value: 105.75), + LineData(time: .string("2018-08-14"), value: 107.25), + LineData(time: .string("2018-08-15"), value: 107.4), + LineData(time: .string("2018-08-16"), value: 110.5), + LineData(time: .string("2018-08-17"), value: 109), + LineData(time: .string("2018-08-20"), value: 108.95), + LineData(time: .string("2018-08-21"), value: 108.35), + LineData(time: .string("2018-08-22"), value: 108.6), + LineData(time: .string("2018-08-23"), value: 105.65), + LineData(time: .string("2018-08-24"), value: 104.45), + LineData(time: .string("2018-08-27"), value: 106.2), + LineData(time: .string("2018-08-28"), value: 106.55), + LineData(time: .string("2018-08-29"), value: 111.8), + LineData(time: .string("2018-08-30"), value: 115.5), + LineData(time: .string("2018-08-31"), value: 115.5), + LineData(time: .string("2018-09-03"), value: 114.55), + LineData(time: .string("2018-09-04"), value: 112.75), + LineData(time: .string("2018-09-05"), value: 111.5), + LineData(time: .string("2018-09-06"), value: 108.1), + LineData(time: .string("2018-09-07"), value: 108.55), + LineData(time: .string("2018-09-10"), value: 106.5), + LineData(time: .string("2018-09-11"), value: 105.1), + LineData(time: .string("2018-09-12"), value: 107.2), + LineData(time: .string("2018-09-13"), value: 107.1), + LineData(time: .string("2018-09-14"), value: 105.75), + LineData(time: .string("2018-09-17"), value: 106.05), + LineData(time: .string("2018-09-18"), value: 109.15), + LineData(time: .string("2018-09-19"), value: 111.4), + LineData(time: .string("2018-09-20"), value: 111), + LineData(time: .string("2018-09-21"), value: 111), + LineData(time: .string("2018-09-24"), value: 108.95), + LineData(time: .string("2018-09-25"), value: 106.65), + LineData(time: .string("2018-09-26"), value: 106.7), + LineData(time: .string("2018-09-27"), value: 107.05), + LineData(time: .string("2018-09-28"), value: 106.55), + LineData(time: .string("2018-10-01"), value: 106.2), + LineData(time: .string("2018-10-02"), value: 106.4), + LineData(time: .string("2018-10-03"), value: 107.1), + LineData(time: .string("2018-10-04"), value: 106.4), + LineData(time: .string("2018-10-05"), value: 104.65), + LineData(time: .string("2018-10-08"), value: 102.65), + LineData(time: .string("2018-10-09"), value: 102.1), + LineData(time: .string("2018-10-10"), value: 102.15), + LineData(time: .string("2018-10-11"), value: 100.9), + LineData(time: .string("2018-10-12"), value: 102), + LineData(time: .string("2018-10-15"), value: 100.15), + LineData(time: .string("2018-10-16"), value: 99), + LineData(time: .string("2018-10-17"), value: 98), + LineData(time: .string("2018-10-18"), value: 96), + LineData(time: .string("2018-10-19"), value: 95.5), + LineData(time: .string("2018-10-22"), value: 92.400002), + LineData(time: .string("2018-10-23"), value: 92.300003), + LineData(time: .string("2018-10-24"), value: 92.900002), + LineData(time: .string("2018-10-25"), value: 91.849998), + LineData(time: .string("2018-10-26"), value: 91.599998), + LineData(time: .string("2018-10-29"), value: 94.050003), + LineData(time: .string("2018-10-30"), value: 98.25), + LineData(time: .string("2018-10-31"), value: 97.25), + LineData(time: .string("2018-11-01"), value: 96.879997), + LineData(time: .string("2018-11-02"), value: 101.78), + LineData(time: .string("2018-11-06"), value: 102.4), + LineData(time: .string("2018-11-07"), value: 100.6), + LineData(time: .string("2018-11-08"), value: 98.5), + LineData(time: .string("2018-11-09"), value: 95.139999), + LineData(time: .string("2018-11-12"), value: 96.900002), + LineData(time: .string("2018-11-13"), value: 97.400002), + LineData(time: .string("2018-11-14"), value: 103.3), + LineData(time: .string("2018-11-15"), value: 102.74), + LineData(time: .string("2018-11-16"), value: 101.2), + LineData(time: .string("2018-11-19"), value: 98.720001), + LineData(time: .string("2018-11-20"), value: 102.2), + LineData(time: .string("2018-11-21"), value: 108.8), + LineData(time: .string("2018-11-22"), value: 109.9), + LineData(time: .string("2018-11-23"), value: 113.74), + LineData(time: .string("2018-11-26"), value: 110.9), + LineData(time: .string("2018-11-27"), value: 113.28), + LineData(time: .string("2018-11-28"), value: 113.6), + LineData(time: .string("2018-11-29"), value: 113.14), + LineData(time: .string("2018-11-30"), value: 114.4), + LineData(time: .string("2018-12-03"), value: 111.84), + LineData(time: .string("2018-12-04"), value: 106.7), + LineData(time: .string("2018-12-05"), value: 107.8), + LineData(time: .string("2018-12-06"), value: 106.44), + LineData(time: .string("2018-12-07"), value: 103.7), + LineData(time: .string("2018-12-10"), value: 101.02), + LineData(time: .string("2018-12-11"), value: 102.72), + LineData(time: .string("2018-12-12"), value: 101.8), + LineData(time: .string("2018-12-13"), value: 102), + LineData(time: .string("2018-12-14"), value: 102.1), + LineData(time: .string("2018-12-17"), value: 101.04), + LineData(time: .string("2018-12-18"), value: 101.6), + LineData(time: .string("2018-12-19"), value: 102), + LineData(time: .string("2018-12-20"), value: 102.02), + LineData(time: .string("2018-12-21"), value: 102.2), + LineData(time: .string("2018-12-24"), value: 102.1), + LineData(time: .string("2018-12-25"), value: 100.8), + LineData(time: .string("2018-12-26"), value: 101.02), + LineData(time: .string("2018-12-27"), value: 100.5), + LineData(time: .string("2018-12-28"), value: 101), + LineData(time: .string("2019-01-03"), value: 101.5), + LineData(time: .string("2019-01-04"), value: 101.1), + LineData(time: .string("2019-01-08"), value: 101.1), + LineData(time: .string("2019-01-09"), value: 102.06), + LineData(time: .string("2019-01-10"), value: 105.14), + LineData(time: .string("2019-01-11"), value: 104.66), + LineData(time: .string("2019-01-14"), value: 106.22), + LineData(time: .string("2019-01-15"), value: 106.98), + LineData(time: .string("2019-01-16"), value: 108.4), + LineData(time: .string("2019-01-17"), value: 109.06), + LineData(time: .string("2019-01-18"), value: 107), + LineData(time: .string("2019-01-21"), value: 105.8), + LineData(time: .string("2019-01-22"), value: 105.24), + LineData(time: .string("2019-01-23"), value: 105.4), + LineData(time: .string("2019-01-24"), value: 105.38), + LineData(time: .string("2019-01-25"), value: 105.7), + LineData(time: .string("2019-01-28"), value: 105.8), + LineData(time: .string("2019-01-29"), value: 106.1), + LineData(time: .string("2019-01-30"), value: 108.6), + LineData(time: .string("2019-01-31"), value: 107.92), + LineData(time: .string("2019-02-01"), value: 105.22), + LineData(time: .string("2019-02-04"), value: 102.44), + LineData(time: .string("2019-02-05"), value: 102.26), + LineData(time: .string("2019-02-06"), value: 102), + LineData(time: .string("2019-02-07"), value: 101.62), + LineData(time: .string("2019-02-08"), value: 101.9), + LineData(time: .string("2019-02-11"), value: 101.78), + LineData(time: .string("2019-02-12"), value: 102.7), + LineData(time: .string("2019-02-13"), value: 100.14), + LineData(time: .string("2019-02-14"), value: 101.36), + LineData(time: .string("2019-02-15"), value: 101.62), + LineData(time: .string("2019-02-18"), value: 100.74), + LineData(time: .string("2019-02-19"), value: 100), + LineData(time: .string("2019-02-20"), value: 100.04), + LineData(time: .string("2019-02-21"), value: 100), + LineData(time: .string("2019-02-22"), value: 100.12), + LineData(time: .string("2019-02-25"), value: 100.04), + LineData(time: .string("2019-02-26"), value: 98.980003), + LineData(time: .string("2019-02-27"), value: 97.699997), + LineData(time: .string("2019-02-28"), value: 97.099998), + LineData(time: .string("2019-03-01"), value: 96.760002), + LineData(time: .string("2019-03-04"), value: 98.360001), + LineData(time: .string("2019-03-05"), value: 96.260002), + LineData(time: .string("2019-03-06"), value: 98.120003), + LineData(time: .string("2019-03-07"), value: 99.68), + LineData(time: .string("2019-03-11"), value: 102.1), + LineData(time: .string("2019-03-12"), value: 100.22), + LineData(time: .string("2019-03-13"), value: 100.5), + LineData(time: .string("2019-03-14"), value: 99.660004), + LineData(time: .string("2019-03-15"), value: 100.08), + LineData(time: .string("2019-03-18"), value: 99.919998), + LineData(time: .string("2019-03-19"), value: 99.459999), + LineData(time: .string("2019-03-20"), value: 98.220001), + LineData(time: .string("2019-03-21"), value: 97.300003), + LineData(time: .string("2019-03-22"), value: 97.660004), + LineData(time: .string("2019-03-25"), value: 97), + LineData(time: .string("2019-03-26"), value: 97.019997), + LineData(time: .string("2019-03-27"), value: 96.099998), + LineData(time: .string("2019-03-28"), value: 96.699997), + LineData(time: .string("2019-03-29"), value: 96.300003), + LineData(time: .string("2019-04-01"), value: 97.779999), + LineData(time: .string("2019-04-02"), value: 98.360001), + LineData(time: .string("2019-04-03"), value: 98.5), + LineData(time: .string("2019-04-04"), value: 98.360001), + LineData(time: .string("2019-04-05"), value: 99.540001), + LineData(time: .string("2019-04-08"), value: 98.580002), + LineData(time: .string("2019-04-09"), value: 97.239998), + LineData(time: .string("2019-04-10"), value: 97.32), + LineData(time: .string("2019-04-11"), value: 98.400002), + LineData(time: .string("2019-04-12"), value: 98.220001), + LineData(time: .string("2019-04-15"), value: 98.720001), + LineData(time: .string("2019-04-16"), value: 99.120003), + LineData(time: .string("2019-04-17"), value: 98.620003), + LineData(time: .string("2019-04-18"), value: 98), + LineData(time: .string("2019-04-19"), value: 97.599998), + LineData(time: .string("2019-04-22"), value: 97.599998), + LineData(time: .string("2019-04-23"), value: 96.800003), + LineData(time: .string("2019-04-24"), value: 96.32), + LineData(time: .string("2019-04-25"), value: 96.339996), + LineData(time: .string("2019-04-26"), value: 97.120003), + LineData(time: .string("2019-04-29"), value: 96.980003), + LineData(time: .string("2019-04-30"), value: 96.32), + LineData(time: .string("2019-05-02"), value: 96.860001), + LineData(time: .string("2019-05-03"), value: 96.699997), + LineData(time: .string("2019-05-06"), value: 94.940002), + LineData(time: .string("2019-05-07"), value: 94.5), + LineData(time: .string("2019-05-08"), value: 94.239998), + LineData(time: .string("2019-05-10"), value: 92.900002), + LineData(time: .string("2019-05-13"), value: 91.279999), + LineData(time: .string("2019-05-14"), value: 91.599998), + LineData(time: .string("2019-05-15"), value: 90.080002), + LineData(time: .string("2019-05-16"), value: 91.68), + LineData(time: .string("2019-05-17"), value: 91.959999), + LineData(time: .string("2019-05-20"), value: 91.080002), + LineData(time: .string("2019-05-21"), value: 90.760002), + LineData(time: .string("2019-05-22"), value: 91), + LineData(time: .string("2019-05-23"), value: 90.739998), + LineData(time: .string("2019-05-24"), value: 91), + LineData(time: .string("2019-05-27"), value: 91.199997), + LineData(time: .string("2019-05-28"), value: 90.68), + LineData(time: .string("2019-05-29"), value: 91.120003), + LineData(time: .string("2019-05-30"), value: 90.419998), + LineData(time: .string("2019-05-31"), value: 93.800003), + LineData(time: .string("2019-06-03"), value: 96.800003), + LineData(time: .string("2019-06-04"), value: 96.34), + LineData(time: .string("2019-06-05"), value: 95.94) + ] + series.setData(data: data) + self.series = series + } + + private func setupSubscription() { + chart.delegate = self + chart.subscribeCrosshairMove() + } + +} + +// MARK: - ChartDelegate +extension MagnifierTooltipViewController: ChartDelegate { + + func didClick(onChart chart: ChartApi, parameters: MouseEventParams) { + + } + + func didCrosshairMove(onChart chart: ChartApi, parameters: MouseEventParams) { + if case let .businessDay(date) = parameters.time, + let point = parameters.point, + case let .barPrice(price) = parameters.price(forSeries: series) { + + let dateString = "\(date.year) - \(date.month) - \(date.day)" + tooltipView.update(title: legend, price: price, date: dateString) + tooltipView.isHidden = false + + let x = CGFloat(point.x) + let targetConstant = x - tooltipView.frame.width * 0.5 + let maximumOffset = self.chart.frame.width - tooltipView.frame.width - 50 + + switch targetConstant { + case ...0: + leadingConstraint.constant = 0 + case maximumOffset...: + leadingConstraint.constant = maximumOffset + default: + leadingConstraint.constant = targetConstant + } + } else { + self.tooltipView.isHidden = true + } + } + + func didVisibleTimeRangeChange(onChart chart: ChartApi, parameters: TimeRange?) { + + } + +} diff --git a/ExampleSPM/LightweightCharts/Example/MarkersViewController.swift b/ExampleSPM/LightweightCharts/Example/MarkersViewController.swift new file mode 100644 index 0000000..8e724d9 --- /dev/null +++ b/ExampleSPM/LightweightCharts/Example/MarkersViewController.swift @@ -0,0 +1,85 @@ +import UIKit +import LightweightCharts + +class MarkersViewController: UIViewController { + + private var chart: LightweightCharts! + private var series: BarSeries! + + override func viewDidLoad() { + super.viewDidLoad() + if #available(iOS 13.0, *) { + view.backgroundColor = .systemBackground + } else { + view.backgroundColor = .white + } + + setupUI() + let data = generateData() + setupData(data) + setupMarkers(data) + } + + private func setupUI() { + let options = ChartOptions() + let chart = LightweightCharts(options: options) + view.addSubview(chart) + chart.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + ]) + } else { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } + self.chart = chart + } + + private func setupData(_ data: [BarData]) { + let series = chart.addBarSeries(options: nil) + series.setData(data: data) + self.series = series + } + + private func setupMarkers(_ data: [BarData]) { + let markers = [ + SeriesMarker(time: data[data.count - 30].time, position: .belowBar, shape: .square, color: "orange", id: nil), + SeriesMarker(time: data[data.count - 30].time, position: .belowBar, shape: .square, color: "yellow", id: nil), + SeriesMarker(time: data[data.count - 30].time, position: .belowBar, shape: .square, color: "red", id: nil), + SeriesMarker(time: data[data.count - 20].time, position: .aboveBar, shape: .square, color: "orange", id: nil), + SeriesMarker(time: data[data.count - 20].time, position: .aboveBar, shape: .square, color: "yellow", id: nil), + SeriesMarker(time: data[data.count - 20].time, position: .aboveBar, shape: .square, color: "red", id: nil), + SeriesMarker(time: data[data.count - 10].time, position: .inBar, shape: .square, color: "orange", id: nil), + SeriesMarker(time: data[data.count - 10].time, position: .inBar, shape: .square, color: "red", id: nil) + ] + series.setMarkers(data: markers) + } + + private func generateData() -> [BarData] { + var time = DateComponents(calendar: .current, year: 2018, day: 0).date! + var result: [BarData] = [] + for i in 0..<500 { + time = Date(timeInterval: 60 * 60 * 24, since: time) + let step = Double(i % 20) / 1000.0 + let base = Double(i) / 5.0 + let barData = BarData( + time: .utc(timestamp: time.timeIntervalSince1970), + open: base * (1 - step), + high: base * (1 + 2 * step), + low: base * (1 - 2 * step), + close: base * (1 + step) + ) + result.append(barData) + } + return result + } + +} diff --git a/ExampleSPM/LightweightCharts/Example/NoPriceScaleViewController.swift b/ExampleSPM/LightweightCharts/Example/NoPriceScaleViewController.swift new file mode 100644 index 0000000..509838f --- /dev/null +++ b/ExampleSPM/LightweightCharts/Example/NoPriceScaleViewController.swift @@ -0,0 +1,215 @@ +import UIKit +import LightweightCharts + +class NoPriceScaleViewController: UIViewController { + + private var chart: LightweightCharts! + private var series: AreaSeries! + + override func viewDidLoad() { + super.viewDidLoad() + if #available(iOS 13.0, *) { + view.backgroundColor = .systemBackground + } else { + view.backgroundColor = .white + } + + setupUI() + setupData() + } + + private func setupUI() { + let options = ChartOptions( + layout: LayoutOptions(backgroundColor: "#fff"), + rightPriceScale: VisiblePriceScaleOptions(visible: false), + grid: GridOptions( + verticalLines: GridLineOptions(visible: false), + horizontalLines: GridLineOptions(visible: false) + ) + ) + let chart = LightweightCharts(options: options) + view.addSubview(chart) + chart.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + ]) + } else { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } + self.chart = chart + } + + private func setupData() { + let options = AreaSeriesOptions( + topColor: "rgba(233, 16, 169, 0.35)", + bottomColor: "rgba(233, 16, 169, 0)", + lineColor: "rgba(233, 16, 169, 1)", + lineWidth: .two + ) + let series = chart.addAreaSeries(options: options) + let data = [ + LineData(time: .string("2016-07-18"), value: 64.04), + LineData(time: .string("2016-07-25"), value: 63.97), + LineData(time: .string("2016-08-01"), value: 66.30), + LineData(time: .string("2016-08-08"), value: 65.32), + LineData(time: .string("2016-08-15"), value: 65.86), + LineData(time: .string("2016-08-22"), value: 66.22), + LineData(time: .string("2016-08-29"), value: 67.49), + LineData(time: .string("2016-09-05"), value: 66.65), + LineData(time: .string("2016-09-12"), value: 65.82), + LineData(time: .string("2016-09-19"), value: 67.25), + LineData(time: .string("2016-09-26"), value: 66.59), + LineData(time: .string("2016-10-03"), value: 68.11), + LineData(time: .string("2016-10-10"), value: 67.52), + LineData(time: .string("2016-10-17"), value: 68.49), + LineData(time: .string("2016-10-24"), value: 69.11), + LineData(time: .string("2016-10-31"), value: 67.76), + LineData(time: .string("2016-11-07"), value: 76.69), + LineData(time: .string("2016-11-14"), value: 77.71), + LineData(time: .string("2016-11-21"), value: 78.83), + LineData(time: .string("2016-11-28"), value: 81.60), + LineData(time: .string("2016-12-05"), value: 85.49), + LineData(time: .string("2016-12-12"), value: 84.94), + LineData(time: .string("2016-12-19"), value: 87.05), + LineData(time: .string("2016-12-26"), value: 86.29), + LineData(time: .string("2017-01-02"), value: 86.12), + LineData(time: .string("2017-01-09"), value: 86.70), + LineData(time: .string("2017-01-16"), value: 83.67), + LineData(time: .string("2017-01-23"), value: 86.93), + LineData(time: .string("2017-01-30"), value: 87.18), + LineData(time: .string("2017-02-06"), value: 87.00), + LineData(time: .string("2017-02-13"), value: 90.23), + LineData(time: .string("2017-02-20"), value: 90.33), + LineData(time: .string("2017-02-27"), value: 92.80), + LineData(time: .string("2017-03-06"), value: 91.28), + LineData(time: .string("2017-03-13"), value: 90.68), + LineData(time: .string("2017-03-20"), value: 87.29), + LineData(time: .string("2017-03-27"), value: 87.84), + LineData(time: .string("2017-04-03"), value: 86.18), + LineData(time: .string("2017-04-10"), value: 84.40), + LineData(time: .string("2017-04-17"), value: 84.52), + LineData(time: .string("2017-04-24"), value: 87.00), + LineData(time: .string("2017-05-01"), value: 87.00), + LineData(time: .string("2017-05-08"), value: 86.92), + LineData(time: .string("2017-05-15"), value: 84.78), + LineData(time: .string("2017-05-22"), value: 85.36), + LineData(time: .string("2017-05-29"), value: 82.64), + LineData(time: .string("2017-06-05"), value: 86.96), + LineData(time: .string("2017-06-12"), value: 86.18), + LineData(time: .string("2017-06-19"), value: 86.86), + LineData(time: .string("2017-06-26"), value: 91.40), + LineData(time: .string("2017-07-03"), value: 93.85), + LineData(time: .string("2017-07-10"), value: 92.25), + LineData(time: .string("2017-07-17"), value: 90.89), + LineData(time: .string("2017-07-24"), value: 91.28), + LineData(time: .string("2017-07-31"), value: 93.66), + LineData(time: .string("2017-08-07"), value: 91.42), + LineData(time: .string("2017-08-14"), value: 90.74), + LineData(time: .string("2017-08-21"), value: 91.89), + LineData(time: .string("2017-08-28"), value: 91.70), + LineData(time: .string("2017-09-04"), value: 88.42), + LineData(time: .string("2017-09-11"), value: 91.62), + LineData(time: .string("2017-09-18"), value: 94.83), + LineData(time: .string("2017-09-25"), value: 95.51), + LineData(time: .string("2017-10-02"), value: 96.92), + LineData(time: .string("2017-10-09"), value: 95.86), + LineData(time: .string("2017-10-16"), value: 99.51), + LineData(time: .string("2017-10-23"), value: 101.77), + LineData(time: .string("2017-10-30"), value: 101.41), + LineData(time: .string("2017-11-06"), value: 97.51), + LineData(time: .string("2017-11-13"), value: 98.14), + LineData(time: .string("2017-11-20"), value: 98.32), + LineData(time: .string("2017-11-27"), value: 104.79), + LineData(time: .string("2017-12-04"), value: 105.93), + LineData(time: .string("2017-12-11"), value: 106.14), + LineData(time: .string("2017-12-18"), value: 107.45), + LineData(time: .string("2017-12-25"), value: 106.94), + LineData(time: .string("2018-01-01"), value: 108.34), + LineData(time: .string("2018-01-08"), value: 112.67), + LineData(time: .string("2018-01-15"), value: 113.01), + LineData(time: .string("2018-01-22"), value: 116.32), + LineData(time: .string("2018-01-29"), value: 114.28), + LineData(time: .string("2018-02-05"), value: 110.04), + LineData(time: .string("2018-02-12"), value: 114.68), + LineData(time: .string("2018-02-19"), value: 117.31), + LineData(time: .string("2018-02-26"), value: 113.32), + LineData(time: .string("2018-03-05"), value: 118.04), + LineData(time: .string("2018-03-12"), value: 115.44), + LineData(time: .string("2018-03-19"), value: 107.01), + LineData(time: .string("2018-03-26"), value: 109.97), + LineData(time: .string("2018-04-02"), value: 109.09), + LineData(time: .string("2018-04-09"), value: 110.30), + LineData(time: .string("2018-04-16"), value: 111.47), + LineData(time: .string("2018-04-23"), value: 109.40), + LineData(time: .string("2018-04-30"), value: 108.43), + LineData(time: .string("2018-05-07"), value: 113.86), + LineData(time: .string("2018-05-14"), value: 111.13), + LineData(time: .string("2018-05-21"), value: 110.66), + LineData(time: .string("2018-05-28"), value: 108.40), + LineData(time: .string("2018-06-04"), value: 111.11), + LineData(time: .string("2018-06-11"), value: 107.90), + LineData(time: .string("2018-06-18"), value: 105.75), + LineData(time: .string("2018-06-25"), value: 104.20), + LineData(time: .string("2018-07-02"), value: 104.06), + LineData(time: .string("2018-07-09"), value: 106.36), + LineData(time: .string("2018-07-16"), value: 111.28), + LineData(time: .string("2018-07-23"), value: 116.03), + LineData(time: .string("2018-07-30"), value: 117.09), + LineData(time: .string("2018-08-06"), value: 115.73), + LineData(time: .string("2018-08-13"), value: 114.77), + LineData(time: .string("2018-08-20"), value: 114.68), + LineData(time: .string("2018-08-27"), value: 114.58), + LineData(time: .string("2018-09-03"), value: 114.32), + LineData(time: .string("2018-09-10"), value: 113.50), + LineData(time: .string("2018-09-17"), value: 117.85), + LineData(time: .string("2018-09-24"), value: 112.84), + LineData(time: .string("2018-10-01"), value: 114.62), + LineData(time: .string("2018-10-08"), value: 106.95), + LineData(time: .string("2018-10-15"), value: 107.91), + LineData(time: .string("2018-10-22"), value: 103.42), + LineData(time: .string("2018-10-29"), value: 108.38), + LineData(time: .string("2018-11-05"), value: 111.29), + LineData(time: .string("2018-11-12"), value: 109.99), + LineData(time: .string("2018-11-19"), value: 106.65), + LineData(time: .string("2018-11-26"), value: 111.19), + LineData(time: .string("2018-12-03"), value: 103.29), + LineData(time: .string("2018-12-10"), value: 100.29), + LineData(time: .string("2018-12-17"), value: 94.17), + LineData(time: .string("2018-12-24"), value: 96.83), + LineData(time: .string("2018-12-31"), value: 100.69), + LineData(time: .string("2019-01-07"), value: 99.91), + LineData(time: .string("2019-01-14"), value: 104.59), + LineData(time: .string("2019-01-21"), value: 103.39), + LineData(time: .string("2019-01-28"), value: 103.88), + LineData(time: .string("2019-02-04"), value: 101.36), + LineData(time: .string("2019-02-11"), value: 105.55), + LineData(time: .string("2019-02-18"), value: 105.00), + LineData(time: .string("2019-02-25"), value: 104.43), + LineData(time: .string("2019-03-04"), value: 103.01), + LineData(time: .string("2019-03-11"), value: 106.55), + LineData(time: .string("2019-03-18"), value: 99.76), + LineData(time: .string("2019-03-25"), value: 101.23), + LineData(time: .string("2019-04-01"), value: 105.31), + LineData(time: .string("2019-04-08"), value: 111.21), + LineData(time: .string("2019-04-15"), value: 113.46), + LineData(time: .string("2019-04-22"), value: 114.47), + LineData(time: .string("2019-04-29"), value: 116.12), + LineData(time: .string("2019-05-06"), value: 112.51), + LineData(time: .string("2019-05-13"), value: 110.77), + LineData(time: .string("2019-05-20"), value: 109.71), + LineData(time: .string("2019-05-27"), value: 109.33) + ] + series.setData(data: data) + self.series = series + } + +} diff --git a/ExampleSPM/LightweightCharts/Example/NoTimeScaleViewController.swift b/ExampleSPM/LightweightCharts/Example/NoTimeScaleViewController.swift new file mode 100644 index 0000000..9511fd2 --- /dev/null +++ b/ExampleSPM/LightweightCharts/Example/NoTimeScaleViewController.swift @@ -0,0 +1,462 @@ +import UIKit +import LightweightCharts + +class NoTimeScaleViewController: UIViewController { + + private var chart: LightweightCharts! + private var areaSeries: AreaSeries! + private var volumeSeries: HistogramSeries! + private let legendLabel = UILabel() + private let dateFormatter: DateFormatter = { + let dateFormatter = DateFormatter() + dateFormatter.dateStyle = .full + return dateFormatter + }() + + private var leadingConstraint: NSLayoutConstraint! + + override func viewDidLoad() { + super.viewDidLoad() + if #available(iOS 13.0, *) { + view.backgroundColor = .systemBackground + } else { + view.backgroundColor = .white + } + + setupUI() + setupData() + setupSubscription() + } + + private func setupUI() { + let options = ChartOptions( + layout: LayoutOptions(backgroundColor: "#fafafa"), + leftPriceScale: VisiblePriceScaleOptions(visible: false), + rightPriceScale: VisiblePriceScaleOptions(visible: false), + timeScale: TimeScaleOptions(visible: false), + crosshair: CrosshairOptions( + vertLine: CrosshairLineOptions(visible: false), + horzLine: CrosshairLineOptions(visible: false) + ), + grid: GridOptions( + verticalLines: GridLineOptions(color: "#fff"), + horizontalLines: GridLineOptions(color: "#fff") + ) + ) + let chart = LightweightCharts(options: options) + view.addSubview(chart) + chart.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + ]) + } else { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } + self.chart = chart + + legendLabel.font = .systemFont(ofSize: 11) + legendLabel.textColor = .white + legendLabel.textAlignment = .center + legendLabel.backgroundColor = UIColor(red: 76/255.0, green: 175/255.0, blue: 80/255.0, alpha: 1) + legendLabel.layer.cornerRadius = 4 + legendLabel.layer.masksToBounds = true + legendLabel.isHidden = true + + view.addSubview(legendLabel) + legendLabel.translatesAutoresizingMaskIntoConstraints = false + leadingConstraint = legendLabel.leadingAnchor.constraint(equalTo: chart.leadingAnchor) + NSLayoutConstraint.activate([ + legendLabel.widthAnchor.constraint(equalToConstant: 128), + legendLabel.heightAnchor.constraint(equalToConstant: 24), + legendLabel.topAnchor.constraint(equalTo: chart.topAnchor, constant: 16), + leadingConstraint + ]) + } + + private func setupData() { + let areaSeriesOptions = AreaSeriesOptions( + topColor: "rgba(76, 175, 80, 0.5)", + bottomColor: "rgba(76, 175, 80, 0)", + lineColor: "rgba(76, 175, 80, 1)", + lineWidth: .two + ) + let areaSeries = chart.addAreaSeries(options: areaSeriesOptions) + let areaData = [ + LineData(time: .string("2018-10-19"), value: 219.31), + LineData(time: .string("2018-10-22"), value: 220.65), + LineData(time: .string("2018-10-23"), value: 222.73), + LineData(time: .string("2018-10-24"), value: 215.09), + LineData(time: .string("2018-10-25"), value: 219.80), + LineData(time: .string("2018-10-26"), value: 216.30), + LineData(time: .string("2018-10-29"), value: 212.24), + LineData(time: .string("2018-10-30"), value: 213.30), + LineData(time: .string("2018-10-31"), value: 218.86), + LineData(time: .string("2018-11-01"), value: 222.22), + LineData(time: .string("2018-11-02"), value: 207.48), + LineData(time: .string("2018-11-05"), value: 201.59), + LineData(time: .string("2018-11-06"), value: 203.77), + LineData(time: .string("2018-11-07"), value: 209.95), + LineData(time: .string("2018-11-08"), value: 208.49), + LineData(time: .string("2018-11-09"), value: 204.47), + LineData(time: .string("2018-11-12"), value: 194.17), + LineData(time: .string("2018-11-13"), value: 192.23), + LineData(time: .string("2018-11-14"), value: 186.80), + LineData(time: .string("2018-11-15"), value: 191.41), + LineData(time: .string("2018-11-16"), value: 193.53), + LineData(time: .string("2018-11-19"), value: 185.86), + LineData(time: .string("2018-11-20"), value: 176.98), + LineData(time: .string("2018-11-21"), value: 176.78), + LineData(time: .string("2018-11-23"), value: 172.29), + LineData(time: .string("2018-11-26"), value: 174.62), + LineData(time: .string("2018-11-27"), value: 174.24), + LineData(time: .string("2018-11-28"), value: 180.94), + LineData(time: .string("2018-11-29"), value: 179.55), + LineData(time: .string("2018-11-30"), value: 178.58), + LineData(time: .string("2018-12-03"), value: 184.82), + LineData(time: .string("2018-12-04"), value: 176.69), + LineData(time: .string("2018-12-06"), value: 174.72), + LineData(time: .string("2018-12-07"), value: 168.49), + LineData(time: .string("2018-12-10"), value: 169.60), + LineData(time: .string("2018-12-11"), value: 168.63), + LineData(time: .string("2018-12-12"), value: 169.10), + LineData(time: .string("2018-12-13"), value: 170.95), + LineData(time: .string("2018-12-14"), value: 165.48), + LineData(time: .string("2018-12-17"), value: 163.94), + LineData(time: .string("2018-12-18"), value: 166.07), + LineData(time: .string("2018-12-19"), value: 160.89), + LineData(time: .string("2018-12-20"), value: 156.83), + LineData(time: .string("2018-12-21"), value: 150.73), + LineData(time: .string("2018-12-24"), value: 146.83), + LineData(time: .string("2018-12-26"), value: 157.17), + LineData(time: .string("2018-12-27"), value: 156.15), + LineData(time: .string("2018-12-28"), value: 156.23), + LineData(time: .string("2018-12-31"), value: 157.74), + LineData(time: .string("2019-01-02"), value: 157.92), + LineData(time: .string("2019-01-03"), value: 142.19), + LineData(time: .string("2019-01-04"), value: 148.26), + LineData(time: .string("2019-01-07"), value: 147.93), + LineData(time: .string("2019-01-08"), value: 150.75), + LineData(time: .string("2019-01-09"), value: 153.31), + LineData(time: .string("2019-01-10"), value: 153.80), + LineData(time: .string("2019-01-11"), value: 152.29), + LineData(time: .string("2019-01-14"), value: 150.00), + LineData(time: .string("2019-01-15"), value: 153.07), + LineData(time: .string("2019-01-16"), value: 154.94), + LineData(time: .string("2019-01-17"), value: 155.86), + LineData(time: .string("2019-01-18"), value: 156.82), + LineData(time: .string("2019-01-22"), value: 153.30), + LineData(time: .string("2019-01-23"), value: 153.92), + LineData(time: .string("2019-01-24"), value: 152.70), + LineData(time: .string("2019-01-25"), value: 157.76), + LineData(time: .string("2019-01-28"), value: 156.30), + LineData(time: .string("2019-01-29"), value: 154.68), + LineData(time: .string("2019-01-30"), value: 165.25), + LineData(time: .string("2019-01-31"), value: 166.44), + LineData(time: .string("2019-02-01"), value: 166.52), + LineData(time: .string("2019-02-04"), value: 171.25), + LineData(time: .string("2019-02-05"), value: 174.18), + LineData(time: .string("2019-02-06"), value: 174.24), + LineData(time: .string("2019-02-07"), value: 170.94), + LineData(time: .string("2019-02-08"), value: 170.41), + LineData(time: .string("2019-02-11"), value: 169.43), + LineData(time: .string("2019-02-12"), value: 170.89), + LineData(time: .string("2019-02-13"), value: 170.18), + LineData(time: .string("2019-02-14"), value: 170.80), + LineData(time: .string("2019-02-15"), value: 170.42), + LineData(time: .string("2019-02-19"), value: 170.93), + LineData(time: .string("2019-02-20"), value: 172.03), + LineData(time: .string("2019-02-21"), value: 171.06), + LineData(time: .string("2019-02-22"), value: 172.97), + LineData(time: .string("2019-02-25"), value: 174.23), + LineData(time: .string("2019-02-26"), value: 174.33), + LineData(time: .string("2019-02-27"), value: 174.87), + LineData(time: .string("2019-02-28"), value: 173.15), + LineData(time: .string("2019-03-01"), value: 174.97), + LineData(time: .string("2019-03-04"), value: 175.85), + LineData(time: .string("2019-03-05"), value: 175.53), + LineData(time: .string("2019-03-06"), value: 174.52), + LineData(time: .string("2019-03-07"), value: 172.50), + LineData(time: .string("2019-03-08"), value: 172.91), + LineData(time: .string("2019-03-11"), value: 178.90), + LineData(time: .string("2019-03-12"), value: 180.91), + LineData(time: .string("2019-03-13"), value: 181.71), + LineData(time: .string("2019-03-14"), value: 183.73), + LineData(time: .string("2019-03-15"), value: 186.12), + LineData(time: .string("2019-03-18"), value: 188.02), + LineData(time: .string("2019-03-19"), value: 186.53), + LineData(time: .string("2019-03-20"), value: 188.16), + LineData(time: .string("2019-03-21"), value: 195.09), + LineData(time: .string("2019-03-22"), value: 191.05), + LineData(time: .string("2019-03-25"), value: 188.74), + LineData(time: .string("2019-03-26"), value: 186.79), + LineData(time: .string("2019-03-27"), value: 188.47), + LineData(time: .string("2019-03-28"), value: 188.72), + LineData(time: .string("2019-03-29"), value: 189.95), + LineData(time: .string("2019-04-01"), value: 191.24), + LineData(time: .string("2019-04-02"), value: 194.02), + LineData(time: .string("2019-04-03"), value: 195.35), + LineData(time: .string("2019-04-04"), value: 195.69), + LineData(time: .string("2019-04-05"), value: 197.00), + LineData(time: .string("2019-04-08"), value: 200.10), + LineData(time: .string("2019-04-09"), value: 199.50), + LineData(time: .string("2019-04-10"), value: 200.62), + LineData(time: .string("2019-04-11"), value: 198.95), + LineData(time: .string("2019-04-12"), value: 198.87), + LineData(time: .string("2019-04-15"), value: 199.23), + LineData(time: .string("2019-04-16"), value: 199.25), + LineData(time: .string("2019-04-17"), value: 203.13), + LineData(time: .string("2019-04-18"), value: 203.86), + LineData(time: .string("2019-04-22"), value: 204.53), + LineData(time: .string("2019-04-23"), value: 207.48), + LineData(time: .string("2019-04-24"), value: 207.16), + LineData(time: .string("2019-04-25"), value: 205.28), + LineData(time: .string("2019-04-26"), value: 204.30), + LineData(time: .string("2019-04-29"), value: 204.61), + LineData(time: .string("2019-04-30"), value: 200.67), + LineData(time: .string("2019-05-01"), value: 210.52), + LineData(time: .string("2019-05-02"), value: 209.15), + LineData(time: .string("2019-05-03"), value: 211.75), + LineData(time: .string("2019-05-06"), value: 208.48), + LineData(time: .string("2019-05-07"), value: 202.86), + LineData(time: .string("2019-05-08"), value: 202.90), + LineData(time: .string("2019-05-09"), value: 200.72), + LineData(time: .string("2019-05-10"), value: 197.18), + LineData(time: .string("2019-05-13"), value: 185.72), + LineData(time: .string("2019-05-14"), value: 188.66), + LineData(time: .string("2019-05-15"), value: 190.92), + LineData(time: .string("2019-05-16"), value: 190.08), + LineData(time: .string("2019-05-17"), value: 189.00), + LineData(time: .string("2019-05-20"), value: 183.09), + LineData(time: .string("2019-05-21"), value: 186.60), + LineData(time: .string("2019-05-22"), value: 182.78), + LineData(time: .string("2019-05-23"), value: 179.66), + LineData(time: .string("2019-05-24"), value: 178.97), + LineData(time: .string("2019-05-28"), value: 178.67) + ] + areaSeries.setData(data: areaData) + self.areaSeries = areaSeries + + let volumeSeriesOptions = HistogramSeriesOptions( + priceScaleId: "123", + priceLineVisible: false, + priceFormat: .builtIn(BuiltInPriceFormat(type: .volume, precision: nil, minMove: nil)), + color: "rgba(76, 175, 80, 0.5)" + ) + let volumeSeries = chart.addHistogramSeries(options: volumeSeriesOptions) + volumeSeries.priceScale().applyOptions( + options: PriceScaleOptions( + scaleMargins: PriceScaleMargins( + top: 0.85, + bottom: 0 + ) + ) + ) + let volumeData = [ + HistogramData(color: nil, time: .string("2018-10-19"), value: 33078726.00), + HistogramData(color: nil, time: .string("2018-10-22"), value: 28792082.00), + HistogramData(color: nil, time: .string("2018-10-23"), value: 38767846.00), + HistogramData(color: nil, time: .string("2018-10-24"), value: 40925163.00), + HistogramData(color: nil, time: .string("2018-10-25"), value: 29855768.00), + HistogramData(color: nil, time: .string("2018-10-26"), value: 47258375.00), + HistogramData(color: nil, time: .string("2018-10-29"), value: 45935520.00), + HistogramData(color: nil, time: .string("2018-10-30"), value: 36659990.00), + HistogramData(color: nil, time: .string("2018-10-31"), value: 38358933.00), + HistogramData(color: nil, time: .string("2018-11-01"), value: 58323180.00), + HistogramData(color: nil, time: .string("2018-11-02"), value: 91328654.00), + HistogramData(color: nil, time: .string("2018-11-05"), value: 66163669.00), + HistogramData(color: nil, time: .string("2018-11-06"), value: 31882881.00), + HistogramData(color: nil, time: .string("2018-11-07"), value: 33424434.00), + HistogramData(color: nil, time: .string("2018-11-08"), value: 25362636.00), + HistogramData(color: nil, time: .string("2018-11-09"), value: 34365750.00), + HistogramData(color: nil, time: .string("2018-11-12"), value: 51135518.00), + HistogramData(color: nil, time: .string("2018-11-13"), value: 46882936.00), + HistogramData(color: nil, time: .string("2018-11-14"), value: 60800957.00), + HistogramData(color: nil, time: .string("2018-11-15"), value: 46478801.00), + HistogramData(color: nil, time: .string("2018-11-16"), value: 36928253.00), + HistogramData(color: nil, time: .string("2018-11-19"), value: 41920872.00), + HistogramData(color: nil, time: .string("2018-11-20"), value: 67825247.00), + HistogramData(color: nil, time: .string("2018-11-21"), value: 31124210.00), + HistogramData(color: nil, time: .string("2018-11-23"), value: 23623972.00), + HistogramData(color: nil, time: .string("2018-11-26"), value: 44998520.00), + HistogramData(color: nil, time: .string("2018-11-27"), value: 41387377.00), + HistogramData(color: nil, time: .string("2018-11-28"), value: 46062539.00), + HistogramData(color: nil, time: .string("2018-11-29"), value: 41769992.00), + HistogramData(color: nil, time: .string("2018-11-30"), value: 39531549.00), + HistogramData(color: nil, time: .string("2018-12-03"), value: 40798002.00), + HistogramData(color: nil, time: .string("2018-12-04"), value: 41344282.00), + HistogramData(color: nil, time: .string("2018-12-06"), value: 43098410.00), + HistogramData(color: nil, time: .string("2018-12-07"), value: 42281631.00), + HistogramData(color: nil, time: .string("2018-12-10"), value: 62025994.00), + HistogramData(color: nil, time: .string("2018-12-11"), value: 47281665.00), + HistogramData(color: nil, time: .string("2018-12-12"), value: 35627674.00), + HistogramData(color: nil, time: .string("2018-12-13"), value: 31897827.00), + HistogramData(color: nil, time: .string("2018-12-14"), value: 40703710.00), + HistogramData(color: nil, time: .string("2018-12-17"), value: 44287922.00), + HistogramData(color: nil, time: .string("2018-12-18"), value: 33841518.00), + HistogramData(color: nil, time: .string("2018-12-19"), value: 49047297.00), + HistogramData(color: nil, time: .string("2018-12-20"), value: 64772960.00), + HistogramData(color: nil, time: .string("2018-12-21"), value: 95744384.00), + HistogramData(color: nil, time: .string("2018-12-24"), value: 37169232.00), + HistogramData(color: nil, time: .string("2018-12-26"), value: 58582544.00), + HistogramData(color: nil, time: .string("2018-12-27"), value: 53117065.00), + HistogramData(color: nil, time: .string("2018-12-28"), value: 42291424.00), + HistogramData(color: nil, time: .string("2018-12-31"), value: 35003466.00), + HistogramData(color: nil, time: .string("2019-01-02"), value: 37039737.00), + HistogramData(color: nil, time: .string("2019-01-03"), value: 91312195.00), + HistogramData(color: nil, time: .string("2019-01-04"), value: 58607070.00), + HistogramData(color: nil, time: .string("2019-01-07"), value: 54777764.00), + HistogramData(color: nil, time: .string("2019-01-08"), value: 41025314.00), + HistogramData(color: nil, time: .string("2019-01-09"), value: 45099081.00), + HistogramData(color: nil, time: .string("2019-01-10"), value: 35780670.00), + HistogramData(color: nil, time: .string("2019-01-11"), value: 27023241.00), + HistogramData(color: nil, time: .string("2019-01-14"), value: 32439186.00), + HistogramData(color: nil, time: .string("2019-01-15"), value: 28710324.00), + HistogramData(color: nil, time: .string("2019-01-16"), value: 30569706.00), + HistogramData(color: nil, time: .string("2019-01-17"), value: 29821160.00), + HistogramData(color: nil, time: .string("2019-01-18"), value: 33751023.00), + HistogramData(color: nil, time: .string("2019-01-22"), value: 30393970.00), + HistogramData(color: nil, time: .string("2019-01-23"), value: 23130570.00), + HistogramData(color: nil, time: .string("2019-01-24"), value: 25441549.00), + HistogramData(color: nil, time: .string("2019-01-25"), value: 33547893.00), + HistogramData(color: nil, time: .string("2019-01-28"), value: 26192058.00), + HistogramData(color: nil, time: .string("2019-01-29"), value: 41587239.00), + HistogramData(color: nil, time: .string("2019-01-30"), value: 61109780.00), + HistogramData(color: nil, time: .string("2019-01-31"), value: 40739649.00), + HistogramData(color: nil, time: .string("2019-02-01"), value: 32668138.00), + HistogramData(color: nil, time: .string("2019-02-04"), value: 31495582.00), + HistogramData(color: nil, time: .string("2019-02-05"), value: 36101628.00), + HistogramData(color: nil, time: .string("2019-02-06"), value: 28239591.00), + HistogramData(color: nil, time: .string("2019-02-07"), value: 31741690.00), + HistogramData(color: nil, time: .string("2019-02-08"), value: 23819966.00), + HistogramData(color: nil, time: .string("2019-02-11"), value: 20993425.00), + HistogramData(color: nil, time: .string("2019-02-12"), value: 22283523.00), + HistogramData(color: nil, time: .string("2019-02-13"), value: 22490233.00), + HistogramData(color: nil, time: .string("2019-02-14"), value: 21835747.00), + HistogramData(color: nil, time: .string("2019-02-15"), value: 24626814.00), + HistogramData(color: nil, time: .string("2019-02-19"), value: 18972826.00), + HistogramData(color: nil, time: .string("2019-02-20"), value: 26114362.00), + HistogramData(color: nil, time: .string("2019-02-21"), value: 17249670.00), + HistogramData(color: nil, time: .string("2019-02-22"), value: 18913154.00), + HistogramData(color: nil, time: .string("2019-02-25"), value: 21873358.00), + HistogramData(color: nil, time: .string("2019-02-26"), value: 17070211.00), + HistogramData(color: nil, time: .string("2019-02-27"), value: 27835389.00), + HistogramData(color: nil, time: .string("2019-02-28"), value: 28215416.00), + HistogramData(color: nil, time: .string("2019-03-01"), value: 25886167.00), + HistogramData(color: nil, time: .string("2019-03-04"), value: 27436203.00), + HistogramData(color: nil, time: .string("2019-03-05"), value: 19737419.00), + HistogramData(color: nil, time: .string("2019-03-06"), value: 20810384.00), + HistogramData(color: nil, time: .string("2019-03-07"), value: 24796374.00), + HistogramData(color: nil, time: .string("2019-03-08"), value: 23999358.00), + HistogramData(color: nil, time: .string("2019-03-11"), value: 32011034.00), + HistogramData(color: nil, time: .string("2019-03-12"), value: 32467584.00), + HistogramData(color: nil, time: .string("2019-03-13"), value: 31032524.00), + HistogramData(color: nil, time: .string("2019-03-14"), value: 23579508.00), + HistogramData(color: nil, time: .string("2019-03-15"), value: 39042912.00), + HistogramData(color: nil, time: .string("2019-03-18"), value: 26219832.00), + HistogramData(color: nil, time: .string("2019-03-19"), value: 31646369.00), + HistogramData(color: nil, time: .string("2019-03-20"), value: 31035231.00), + HistogramData(color: nil, time: .string("2019-03-21"), value: 51034237.00), + HistogramData(color: nil, time: .string("2019-03-22"), value: 42407666.00), + HistogramData(color: nil, time: .string("2019-03-25"), value: 43845293.00), + HistogramData(color: nil, time: .string("2019-03-26"), value: 49800538.00), + HistogramData(color: nil, time: .string("2019-03-27"), value: 29848427.00), + HistogramData(color: nil, time: .string("2019-03-28"), value: 20780363.00), + HistogramData(color: nil, time: .string("2019-03-29"), value: 23563961.00), + HistogramData(color: nil, time: .string("2019-04-01"), value: 27861964.00), + HistogramData(color: nil, time: .string("2019-04-02"), value: 22765732.00), + HistogramData(color: nil, time: .string("2019-04-03"), value: 23271830.00), + HistogramData(color: nil, time: .string("2019-04-04"), value: 19114275.00), + HistogramData(color: nil, time: .string("2019-04-05"), value: 18526644.00), + HistogramData(color: nil, time: .string("2019-04-08"), value: 25881697.00), + HistogramData(color: nil, time: .string("2019-04-09"), value: 35768237.00), + HistogramData(color: nil, time: .string("2019-04-10"), value: 21695288.00), + HistogramData(color: nil, time: .string("2019-04-11"), value: 20900808.00), + HistogramData(color: nil, time: .string("2019-04-12"), value: 27760668.00), + HistogramData(color: nil, time: .string("2019-04-15"), value: 17536646.00), + HistogramData(color: nil, time: .string("2019-04-16"), value: 25696385.00), + HistogramData(color: nil, time: .string("2019-04-17"), value: 28906780.00), + HistogramData(color: nil, time: .string("2019-04-18"), value: 24195766.00), + HistogramData(color: nil, time: .string("2019-04-22"), value: 19439545.00), + HistogramData(color: nil, time: .string("2019-04-23"), value: 23322991.00), + HistogramData(color: nil, time: .string("2019-04-24"), value: 17540609.00), + HistogramData(color: nil, time: .string("2019-04-25"), value: 18543206.00), + HistogramData(color: nil, time: .string("2019-04-26"), value: 18649102.00), + HistogramData(color: nil, time: .string("2019-04-29"), value: 22204716.00), + HistogramData(color: nil, time: .string("2019-04-30"), value: 46534923.00), + HistogramData(color: nil, time: .string("2019-05-01"), value: 64827328.00), + HistogramData(color: nil, time: .string("2019-05-02"), value: 31996324.00), + HistogramData(color: nil, time: .string("2019-05-03"), value: 20892378.00), + HistogramData(color: nil, time: .string("2019-05-06"), value: 32443113.00), + HistogramData(color: nil, time: .string("2019-05-07"), value: 38763698.00), + HistogramData(color: nil, time: .string("2019-05-08"), value: 26339504.00), + HistogramData(color: nil, time: .string("2019-05-09"), value: 34908607.00), + HistogramData(color: nil, time: .string("2019-05-10"), value: 41208712.00), + HistogramData(color: nil, time: .string("2019-05-13"), value: 57430623.00), + HistogramData(color: nil, time: .string("2019-05-14"), value: 36529677.00), + HistogramData(color: nil, time: .string("2019-05-15"), value: 26544718.00), + HistogramData(color: nil, time: .string("2019-05-16"), value: 33031364.00), + HistogramData(color: nil, time: .string("2019-05-17"), value: 32879090.00), + HistogramData(color: nil, time: .string("2019-05-20"), value: 38690198.00), + HistogramData(color: nil, time: .string("2019-05-21"), value: 28364848.00), + HistogramData(color: nil, time: .string("2019-05-22"), value: 29748556.00), + HistogramData(color: nil, time: .string("2019-05-23"), value: 36217464.00), + HistogramData(color: nil, time: .string("2019-05-24"), value: 23714686.00), + HistogramData(color: nil, time: .string("2019-05-28"), value: 9264013.00) + ] + volumeSeries.setData(data: volumeData) + self.volumeSeries = volumeSeries + } + + private func setupSubscription() { + chart.delegate = self + chart.subscribeCrosshairMove() + } + +} + +// MARK: - ChartDelegate +extension NoTimeScaleViewController: ChartDelegate { + + func didClick(onChart chart: ChartApi, parameters: MouseEventParams) { + + } + + func didCrosshairMove(onChart chart: ChartApi, parameters: MouseEventParams) { + guard case let .barPrice(price) = parameters.price(forSeries: areaSeries), + let time = parameters.time, + let point = parameters.point + else { + legendLabel.isHidden = true + return + } + + let dateString: String + switch time { + case let .businessDay(time): + dateString = "\(time.year)-\(time.month)-\(time.day)" + case let .utc(timestamp: time): + let date = Date(timeIntervalSince1970: TimeInterval(time)) + dateString = dateFormatter.string(from: date) + } + + legendLabel.text = "\((price * 100 / 100).rounded()) | \(dateString)" + legendLabel.isHidden = false + let leading = CGFloat(point.x) - legendLabel.frame.width / 2 + let constant = max(0, min(self.chart.frame.width - legendLabel.frame.width, leading)) + leadingConstraint.constant = constant + } + + func didVisibleTimeRangeChange(onChart chart: ChartApi, parameters: TimeRange?) { + + } + +} diff --git a/ExampleSPM/LightweightCharts/Example/PercentagePriceScaleViewController.swift b/ExampleSPM/LightweightCharts/Example/PercentagePriceScaleViewController.swift new file mode 100644 index 0000000..66b7844 --- /dev/null +++ b/ExampleSPM/LightweightCharts/Example/PercentagePriceScaleViewController.swift @@ -0,0 +1,379 @@ +import UIKit +import LightweightCharts + +class PercentagePriceScaleViewController: UIViewController { + + private var chart: LightweightCharts! + private var areaSeries: AreaSeries! + private var extraSeries: AreaSeries! + + override func viewDidLoad() { + super.viewDidLoad() + if #available(iOS 13.0, *) { + view.backgroundColor = .systemBackground + } else { + view.backgroundColor = .white + } + + setupUI() + setupData() + } + + private func setupUI() { + let options = ChartOptions( + layout: LayoutOptions(backgroundColor: "#100841", textColor: "#ffffff"), + rightPriceScale: VisiblePriceScaleOptions(mode: .percentage), + timeScale: TimeScaleOptions(borderColor: "rgba(197, 203, 206, 0.4)"), + grid: GridOptions( + verticalLines: GridLineOptions(color: "rgba(197, 203, 206, 0.7)", style: .dotted), + horizontalLines: GridLineOptions(color: "rgba(197, 203, 206, 0.7)", style: .dotted) + ) + ) + let chart = LightweightCharts(options: options) + view.addSubview(chart) + chart.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + ]) + } else { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } + self.chart = chart + } + + private func setupData() { + let areaSeriesOptions = AreaSeriesOptions( + topColor: "rgba(67, 83, 254, 0.7)", + bottomColor: "rgba(67, 83, 254, 0.3)", + lineColor: "rgba(67, 83, 254, 1)", + lineWidth: .two + ) + let areaSeries = chart.addAreaSeries(options: areaSeriesOptions) + let areaData = [ + LineData(time: .string("2018-10-19"), value: 219.31), + LineData(time: .string("2018-10-22"), value: 220.65), + LineData(time: .string("2018-10-23"), value: 222.73), + LineData(time: .string("2018-10-24"), value: 215.09), + LineData(time: .string("2018-10-25"), value: 219.8), + LineData(time: .string("2018-10-26"), value: 216.3), + LineData(time: .string("2018-10-29"), value: 212.24), + LineData(time: .string("2018-10-30"), value: 213.3), + LineData(time: .string("2018-10-31"), value: 218.86), + LineData(time: .string("2018-11-01"), value: 222.22), + LineData(time: .string("2018-11-02"), value: 207.48), + LineData(time: .string("2018-11-05"), value: 201.59), + LineData(time: .string("2018-11-06"), value: 203.77), + LineData(time: .string("2018-11-07"), value: 209.95), + LineData(time: .string("2018-11-08"), value: 208.49), + LineData(time: .string("2018-11-09"), value: 204.47), + LineData(time: .string("2018-11-12"), value: 194.17), + LineData(time: .string("2018-11-13"), value: 192.23), + LineData(time: .string("2018-11-14"), value: 186.8), + LineData(time: .string("2018-11-15"), value: 191.41), + LineData(time: .string("2018-11-16"), value: 193.53), + LineData(time: .string("2018-11-19"), value: 185.86), + LineData(time: .string("2018-11-20"), value: 176.98), + LineData(time: .string("2018-11-21"), value: 176.78), + LineData(time: .string("2018-11-23"), value: 172.29), + LineData(time: .string("2018-11-26"), value: 174.62), + LineData(time: .string("2018-11-27"), value: 174.24), + LineData(time: .string("2018-11-28"), value: 180.94), + LineData(time: .string("2018-11-29"), value: 179.55), + LineData(time: .string("2018-11-30"), value: 178.58), + LineData(time: .string("2018-12-03"), value: 184.82), + LineData(time: .string("2018-12-04"), value: 176.69), + LineData(time: .string("2018-12-06"), value: 174.72), + LineData(time: .string("2018-12-07"), value: 168.49), + LineData(time: .string("2018-12-10"), value: 169.6), + LineData(time: .string("2018-12-11"), value: 168.63), + LineData(time: .string("2018-12-12"), value: 169.1), + LineData(time: .string("2018-12-13"), value: 170.95), + LineData(time: .string("2018-12-14"), value: 165.48), + LineData(time: .string("2018-12-17"), value: 163.94), + LineData(time: .string("2018-12-18"), value: 166.07), + LineData(time: .string("2018-12-19"), value: 160.89), + LineData(time: .string("2018-12-20"), value: 156.83), + LineData(time: .string("2018-12-21"), value: 150.73), + LineData(time: .string("2018-12-24"), value: 146.83), + LineData(time: .string("2018-12-26"), value: 157.17), + LineData(time: .string("2018-12-27"), value: 156.15), + LineData(time: .string("2018-12-28"), value: 156.23), + LineData(time: .string("2018-12-31"), value: 157.74), + LineData(time: .string("2019-01-02"), value: 157.92), + LineData(time: .string("2019-01-03"), value: 142.19), + LineData(time: .string("2019-01-04"), value: 148.26), + LineData(time: .string("2019-01-07"), value: 147.93), + LineData(time: .string("2019-01-08"), value: 150.75), + LineData(time: .string("2019-01-09"), value: 153.31), + LineData(time: .string("2019-01-10"), value: 153.8), + LineData(time: .string("2019-01-11"), value: 152.29), + LineData(time: .string("2019-01-14"), value: 150), + LineData(time: .string("2019-01-15"), value: 153.07), + LineData(time: .string("2019-01-16"), value: 154.94), + LineData(time: .string("2019-01-17"), value: 155.86), + LineData(time: .string("2019-01-18"), value: 156.82), + LineData(time: .string("2019-01-22"), value: 153.3), + LineData(time: .string("2019-01-23"), value: 153.92), + LineData(time: .string("2019-01-24"), value: 152.7), + LineData(time: .string("2019-01-25"), value: 157.76), + LineData(time: .string("2019-01-28"), value: 156.3), + LineData(time: .string("2019-01-29"), value: 154.68), + LineData(time: .string("2019-01-30"), value: 165.25), + LineData(time: .string("2019-01-31"), value: 166.44), + LineData(time: .string("2019-02-01"), value: 166.52), + LineData(time: .string("2019-02-04"), value: 171.25), + LineData(time: .string("2019-02-05"), value: 174.18), + LineData(time: .string("2019-02-06"), value: 174.24), + LineData(time: .string("2019-02-07"), value: 170.94), + LineData(time: .string("2019-02-08"), value: 170.41), + LineData(time: .string("2019-02-11"), value: 169.43), + LineData(time: .string("2019-02-12"), value: 170.89), + LineData(time: .string("2019-02-13"), value: 170.18), + LineData(time: .string("2019-02-14"), value: 170.8), + LineData(time: .string("2019-02-15"), value: 170.42), + LineData(time: .string("2019-02-19"), value: 170.93), + LineData(time: .string("2019-02-20"), value: 172.03), + LineData(time: .string("2019-02-21"), value: 171.06), + LineData(time: .string("2019-02-22"), value: 172.97), + LineData(time: .string("2019-02-25"), value: 174.23), + LineData(time: .string("2019-02-26"), value: 174.33), + LineData(time: .string("2019-02-27"), value: 174.87), + LineData(time: .string("2019-02-28"), value: 173.15), + LineData(time: .string("2019-03-01"), value: 174.97), + LineData(time: .string("2019-03-04"), value: 175.85), + LineData(time: .string("2019-03-05"), value: 175.53), + LineData(time: .string("2019-03-06"), value: 174.52), + LineData(time: .string("2019-03-07"), value: 172.5), + LineData(time: .string("2019-03-08"), value: 172.91), + LineData(time: .string("2019-03-11"), value: 178.9), + LineData(time: .string("2019-03-12"), value: 180.91), + LineData(time: .string("2019-03-13"), value: 181.71), + LineData(time: .string("2019-03-14"), value: 183.73), + LineData(time: .string("2019-03-15"), value: 186.12), + LineData(time: .string("2019-03-18"), value: 188.02), + LineData(time: .string("2019-03-19"), value: 186.53), + LineData(time: .string("2019-03-20"), value: 188.16), + LineData(time: .string("2019-03-21"), value: 195.09), + LineData(time: .string("2019-03-22"), value: 191.05), + LineData(time: .string("2019-03-25"), value: 188.74), + LineData(time: .string("2019-03-26"), value: 186.79), + LineData(time: .string("2019-03-27"), value: 188.47), + LineData(time: .string("2019-03-28"), value: 188.72), + LineData(time: .string("2019-03-29"), value: 189.95), + LineData(time: .string("2019-04-01"), value: 191.24), + LineData(time: .string("2019-04-02"), value: 194.02), + LineData(time: .string("2019-04-03"), value: 195.35), + LineData(time: .string("2019-04-04"), value: 195.69), + LineData(time: .string("2019-04-05"), value: 197), + LineData(time: .string("2019-04-08"), value: 200.1), + LineData(time: .string("2019-04-09"), value: 199.5), + LineData(time: .string("2019-04-10"), value: 200.62), + LineData(time: .string("2019-04-11"), value: 198.95), + LineData(time: .string("2019-04-12"), value: 198.87), + LineData(time: .string("2019-04-15"), value: 199.23), + LineData(time: .string("2019-04-16"), value: 199.25), + LineData(time: .string("2019-04-17"), value: 203.13), + LineData(time: .string("2019-04-18"), value: 203.86), + LineData(time: .string("2019-04-22"), value: 204.53), + LineData(time: .string("2019-04-23"), value: 207.48), + LineData(time: .string("2019-04-24"), value: 207.16), + LineData(time: .string("2019-04-25"), value: 205.28), + LineData(time: .string("2019-04-26"), value: 204.3), + LineData(time: .string("2019-04-29"), value: 204.61), + LineData(time: .string("2019-04-30"), value: 200.67), + LineData(time: .string("2019-05-01"), value: 210.52), + LineData(time: .string("2019-05-02"), value: 209.15), + LineData(time: .string("2019-05-03"), value: 211.75), + LineData(time: .string("2019-05-06"), value: 208.48), + LineData(time: .string("2019-05-07"), value: 202.86), + LineData(time: .string("2019-05-08"), value: 202.9), + LineData(time: .string("2019-05-09"), value: 200.72), + LineData(time: .string("2019-05-10"), value: 197.18), + LineData(time: .string("2019-05-13"), value: 185.72), + LineData(time: .string("2019-05-14"), value: 188.66), + LineData(time: .string("2019-05-15"), value: 190.92), + LineData(time: .string("2019-05-16"), value: 190.08), + LineData(time: .string("2019-05-17"), value: 189), + LineData(time: .string("2019-05-20"), value: 183.09), + LineData(time: .string("2019-05-21"), value: 186.6), + LineData(time: .string("2019-05-22"), value: 182.78), + LineData(time: .string("2019-05-23"), value: 179.66), + LineData(time: .string("2019-05-24"), value: 178.97), + LineData(time: .string("2019-05-28"), value: 179.07) + ] + areaSeries.setData(data: areaData) + self.areaSeries = areaSeries + + let extraSeriesOptions = AreaSeriesOptions( + topColor: "rgba(255, 192, 0, 0.7)", + bottomColor: "rgba(255, 192, 0, 0.3)", + lineColor: "rgba(255, 192, 0, 1)", + lineWidth: .two + ) + let extraSeries = chart.addAreaSeries(options: extraSeriesOptions) + let extraData = [ + LineData(time: .string("2018-10-19"), value: 44), + LineData(time: .string("2018-10-22"), value: 43.14), + LineData(time: .string("2018-10-23"), value: 42.3), + LineData(time: .string("2018-10-24"), value: 40.99), + LineData(time: .string("2018-10-25"), value: 41.59), + LineData(time: .string("2018-10-26"), value: 41.1), + LineData(time: .string("2018-10-29"), value: 41.03), + LineData(time: .string("2018-10-30"), value: 42.21), + LineData(time: .string("2018-10-31"), value: 43.37), + LineData(time: .string("2018-11-01"), value: 42.65), + LineData(time: .string("2018-11-02"), value: 41.6), + LineData(time: .string("2018-11-05"), value: 42.61), + LineData(time: .string("2018-11-06"), value: 42.66), + LineData(time: .string("2018-11-07"), value: 43.11), + LineData(time: .string("2018-11-08"), value: 41.27), + LineData(time: .string("2018-11-09"), value: 41.24), + LineData(time: .string("2018-11-12"), value: 40.87), + LineData(time: .string("2018-11-13"), value: 39.81), + LineData(time: .string("2018-11-14"), value: 40.33), + LineData(time: .string("2018-11-15"), value: 41.16), + LineData(time: .string("2018-11-16"), value: 40.84), + LineData(time: .string("2018-11-19"), value: 40.92), + LineData(time: .string("2018-11-20"), value: 40.1), + LineData(time: .string("2018-11-21"), value: 41.27), + LineData(time: .string("2018-11-23"), value: 39.89), + LineData(time: .string("2018-11-26"), value: 40.53), + LineData(time: .string("2018-11-27"), value: 40.32), + LineData(time: .string("2018-11-28"), value: 40.84), + LineData(time: .string("2018-11-29"), value: 40.48), + LineData(time: .string("2018-11-30"), value: 40.35), + LineData(time: .string("2018-12-03"), value: 41.19), + LineData(time: .string("2018-12-04"), value: 40.95), + LineData(time: .string("2018-12-06"), value: 39.59), + LineData(time: .string("2018-12-07"), value: 39.51), + LineData(time: .string("2018-12-10"), value: 39.37), + LineData(time: .string("2018-12-11"), value: 39.08), + LineData(time: .string("2018-12-12"), value: 39.05), + LineData(time: .string("2018-12-13"), value: 39.29), + LineData(time: .string("2018-12-14"), value: 38.66), + LineData(time: .string("2018-12-17"), value: 38.41), + LineData(time: .string("2018-12-18"), value: 37.82), + LineData(time: .string("2018-12-19"), value: 37.65), + LineData(time: .string("2018-12-20"), value: 37.26), + LineData(time: .string("2018-12-21"), value: 37.67), + LineData(time: .string("2018-12-24"), value: 36.65), + LineData(time: .string("2018-12-26"), value: 38.06), + LineData(time: .string("2018-12-27"), value: 37.73), + LineData(time: .string("2018-12-28"), value: 38.13), + LineData(time: .string("2018-12-31"), value: 37.92), + LineData(time: .string("2019-01-02"), value: 38.59), + LineData(time: .string("2019-01-03"), value: 38.81), + LineData(time: .string("2019-01-04"), value: 40.03), + LineData(time: .string("2019-01-07"), value: 40.16), + LineData(time: .string("2019-01-08"), value: 40.03), + LineData(time: .string("2019-01-09"), value: 40.36), + LineData(time: .string("2019-01-10"), value: 40.7), + LineData(time: .string("2019-01-11"), value: 40.24), + LineData(time: .string("2019-01-14"), value: 40.42), + LineData(time: .string("2019-01-15"), value: 40.24), + LineData(time: .string("2019-01-16"), value: 40.12), + LineData(time: .string("2019-01-17"), value: 40.13), + LineData(time: .string("2019-01-18"), value: 40.76), + LineData(time: .string("2019-01-22"), value: 40.08), + LineData(time: .string("2019-01-23"), value: 40.12), + LineData(time: .string("2019-01-24"), value: 40.11), + LineData(time: .string("2019-01-25"), value: 40.11), + LineData(time: .string("2019-01-28"), value: 39.57), + LineData(time: .string("2019-01-29"), value: 40.2), + LineData(time: .string("2019-01-30"), value: 40.67), + LineData(time: .string("2019-01-31"), value: 41.12), + LineData(time: .string("2019-02-01"), value: 41.34), + LineData(time: .string("2019-02-04"), value: 41.39), + LineData(time: .string("2019-02-05"), value: 42.82), + LineData(time: .string("2019-02-06"), value: 43.04), + LineData(time: .string("2019-02-07"), value: 42.7), + LineData(time: .string("2019-02-08"), value: 42.49), + LineData(time: .string("2019-02-11"), value: 42.21), + LineData(time: .string("2019-02-12"), value: 42.42), + LineData(time: .string("2019-02-13"), value: 42.64), + LineData(time: .string("2019-02-14"), value: 41.87), + LineData(time: .string("2019-02-15"), value: 42.29), + LineData(time: .string("2019-02-19"), value: 42.38), + LineData(time: .string("2019-02-20"), value: 42.48), + LineData(time: .string("2019-02-21"), value: 42.29), + LineData(time: .string("2019-02-22"), value: 42.46), + LineData(time: .string("2019-02-25"), value: 42.51), + LineData(time: .string("2019-02-26"), value: 42.52), + LineData(time: .string("2019-02-27"), value: 42.84), + LineData(time: .string("2019-02-28"), value: 42.65), + LineData(time: .string("2019-03-01"), value: 42.58), + LineData(time: .string("2019-03-04"), value: 42.64), + LineData(time: .string("2019-03-05"), value: 42.74), + LineData(time: .string("2019-03-06"), value: 42.7), + LineData(time: .string("2019-03-07"), value: 42.63), + LineData(time: .string("2019-03-08"), value: 42.25), + LineData(time: .string("2019-03-11"), value: 42.33), + LineData(time: .string("2019-03-12"), value: 42.46), + LineData(time: .string("2019-03-13"), value: 43.83), + LineData(time: .string("2019-03-14"), value: 43.95), + LineData(time: .string("2019-03-15"), value: 43.87), + LineData(time: .string("2019-03-18"), value: 44.24), + LineData(time: .string("2019-03-19"), value: 44.47), + LineData(time: .string("2019-03-20"), value: 44.53), + LineData(time: .string("2019-03-21"), value: 44.53), + LineData(time: .string("2019-03-22"), value: 43.95), + LineData(time: .string("2019-03-25"), value: 43.53), + LineData(time: .string("2019-03-26"), value: 43.82), + LineData(time: .string("2019-03-27"), value: 43.59), + LineData(time: .string("2019-03-28"), value: 43.63), + LineData(time: .string("2019-03-29"), value: 43.72), + LineData(time: .string("2019-04-01"), value: 44.09), + LineData(time: .string("2019-04-02"), value: 44.23), + LineData(time: .string("2019-04-03"), value: 44.23), + LineData(time: .string("2019-04-04"), value: 44.15), + LineData(time: .string("2019-04-05"), value: 44.53), + LineData(time: .string("2019-04-08"), value: 45.23), + LineData(time: .string("2019-04-09"), value: 44.99), + LineData(time: .string("2019-04-10"), value: 45.04), + LineData(time: .string("2019-04-11"), value: 44.87), + LineData(time: .string("2019-04-12"), value: 44.67), + LineData(time: .string("2019-04-15"), value: 44.67), + LineData(time: .string("2019-04-16"), value: 44.48), + LineData(time: .string("2019-04-17"), value: 44.62), + LineData(time: .string("2019-04-18"), value: 44.39), + LineData(time: .string("2019-04-22"), value: 45.04), + LineData(time: .string("2019-04-23"), value: 45.02), + LineData(time: .string("2019-04-24"), value: 44.13), + LineData(time: .string("2019-04-25"), value: 43.96), + LineData(time: .string("2019-04-26"), value: 43.31), + LineData(time: .string("2019-04-29"), value: 43.02), + LineData(time: .string("2019-04-30"), value: 43.73), + LineData(time: .string("2019-05-01"), value: 43.08), + LineData(time: .string("2019-05-02"), value: 42.63), + LineData(time: .string("2019-05-03"), value: 43.08), + LineData(time: .string("2019-05-06"), value: 42.93), + LineData(time: .string("2019-05-07"), value: 42.22), + LineData(time: .string("2019-05-08"), value: 42.28), + LineData(time: .string("2019-05-09"), value: 41.65), + LineData(time: .string("2019-05-10"), value: 41.5), + LineData(time: .string("2019-05-13"), value: 41.23), + LineData(time: .string("2019-05-14"), value: 41.55), + LineData(time: .string("2019-05-15"), value: 41.77), + LineData(time: .string("2019-05-16"), value: 42.28), + LineData(time: .string("2019-05-17"), value: 42.34), + LineData(time: .string("2019-05-20"), value: 42.58), + LineData(time: .string("2019-05-21"), value: 42.75), + LineData(time: .string("2019-05-22"), value: 42.34), + LineData(time: .string("2019-05-23"), value: 41.34), + LineData(time: .string("2019-05-24"), value: 41.76), + LineData(time: .string("2019-05-28"), value: 41.625) + ] + extraSeries.setData(data: extraData) + self.extraSeries = extraSeries + } + +} diff --git a/ExampleSPM/LightweightCharts/Example/PriceLineViewController.swift b/ExampleSPM/LightweightCharts/Example/PriceLineViewController.swift new file mode 100644 index 0000000..edfff28 --- /dev/null +++ b/ExampleSPM/LightweightCharts/Example/PriceLineViewController.swift @@ -0,0 +1,83 @@ +import UIKit +import LightweightCharts + +class PriceLineViewController: UIViewController { + + private var chart: LightweightCharts! + private var series: LineSeries! + private var priceLine: PriceLine! + + override func viewDidLoad() { + super.viewDidLoad() + if #available(iOS 13.0, *) { + view.backgroundColor = .systemBackground + } else { + view.backgroundColor = .white + } + + setupUI() + setupData() + setupPriceLine() + + let options = PriceLineOptions( + price: 20, + color: "#00FF00", + lineWidth: .two, + lineStyle: .dotted + ) + priceLine.applyOptions(options: options) + } + + private func setupUI() { + let options = ChartOptions() + let chart = LightweightCharts(options: options) + view.addSubview(chart) + chart.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + ]) + } else { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } + self.chart = chart + } + + private func setupData() { + let series = chart.addLineSeries(options: nil) + let data = generateData() + series.setData(data: data) + self.series = series + } + + private func setupPriceLine() { + let options = PriceLineOptions( + price: 10, + color: "red", + lineWidth: .one, + lineStyle: .solid + ) + let priceLine = series.createPriceLine(options: options) + self.priceLine = priceLine + } + + private func generateData() -> [LineData] { + var time = DateComponents(calendar: .current, year: 2018, day: 0).date! + var result: [LineData] = [] + for i in 0..<60 { + time = Date(timeInterval: 60 * 60 * 24, since: time) + let lineData = LineData(time: .utc(timestamp: time.timeIntervalSince1970), value: Double(i)) + result.append(lineData) + } + return result + } + +} diff --git a/ExampleSPM/LightweightCharts/Example/PriceScaleAtLeftViewController.swift b/ExampleSPM/LightweightCharts/Example/PriceScaleAtLeftViewController.swift new file mode 100644 index 0000000..d01641d --- /dev/null +++ b/ExampleSPM/LightweightCharts/Example/PriceScaleAtLeftViewController.swift @@ -0,0 +1,211 @@ +import UIKit +import LightweightCharts + +class PriceScaleAtLeftViewController: UIViewController { + + private var chart: LightweightCharts! + private var series: AreaSeries! + + override func viewDidLoad() { + super.viewDidLoad() + if #available(iOS 13.0, *) { + view.backgroundColor = .systemBackground + } else { + view.backgroundColor = .white + } + + setupUI() + setupData() + } + + private func setupUI() { + let options = ChartOptions( + leftPriceScale: VisiblePriceScaleOptions(visible: true), + rightPriceScale: VisiblePriceScaleOptions(visible: false) + ) + let chart = LightweightCharts(options: options) + view.addSubview(chart) + chart.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + ]) + } else { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } + self.chart = chart + } + + private func setupData() { + let options = AreaSeriesOptions( + topColor: "rgba(251, 192, 45, 0.56)", + bottomColor: "rgba(251, 192, 45, 0.04)", + lineColor: "rgba(251, 192, 45, 1)", + lineWidth: .two + ) + let series = chart.addAreaSeries(options: options) + let data = [ + LineData(time: .string("2018-10-19"), value: 154.05), + LineData(time: .string("2018-10-22"), value: 154.78), + LineData(time: .string("2018-10-23"), value: 154.39), + LineData(time: .string("2018-10-24"), value: 146.04), + LineData(time: .string("2018-10-25"), value: 150.95), + LineData(time: .string("2018-10-26"), value: 145.37), + LineData(time: .string("2018-10-29"), value: 142.09), + LineData(time: .string("2018-10-30"), value: 146.22), + LineData(time: .string("2018-10-31"), value: 151.79), + LineData(time: .string("2018-11-01"), value: 151.75), + LineData(time: .string("2018-11-02"), value: 150.35), + LineData(time: .string("2018-11-05"), value: 148.68), + LineData(time: .string("2018-11-06"), value: 149.94), + LineData(time: .string("2018-11-07"), value: 151.53), + LineData(time: .string("2018-11-08"), value: 147.87), + LineData(time: .string("2018-11-09"), value: 144.96), + LineData(time: .string("2018-11-12"), value: 141.55), + LineData(time: .string("2018-11-13"), value: 142.16), + LineData(time: .string("2018-11-14"), value: 144.22), + LineData(time: .string("2018-11-15"), value: 143.85), + LineData(time: .string("2018-11-16"), value: 139.53), + LineData(time: .string("2018-11-19"), value: 131.55), + LineData(time: .string("2018-11-20"), value: 132.43), + LineData(time: .string("2018-11-21"), value: 134.82), + LineData(time: .string("2018-11-23"), value: 131.73), + LineData(time: .string("2018-11-26"), value: 136.38), + LineData(time: .string("2018-11-27"), value: 135.00), + LineData(time: .string("2018-11-28"), value: 136.76), + LineData(time: .string("2018-11-29"), value: 138.68), + LineData(time: .string("2018-11-30"), value: 140.61), + LineData(time: .string("2018-12-03"), value: 141.09), + LineData(time: .string("2018-12-04"), value: 137.93), + LineData(time: .string("2018-12-06"), value: 139.63), + LineData(time: .string("2018-12-07"), value: 137.42), + LineData(time: .string("2018-12-10"), value: 141.85), + LineData(time: .string("2018-12-11"), value: 142.08), + LineData(time: .string("2018-12-12"), value: 144.50), + LineData(time: .string("2018-12-13"), value: 145.01), + LineData(time: .string("2018-12-14"), value: 144.06), + LineData(time: .string("2018-12-17"), value: 140.19), + LineData(time: .string("2018-12-18"), value: 143.66), + LineData(time: .string("2018-12-19"), value: 133.24), + LineData(time: .string("2018-12-20"), value: 133.40), + LineData(time: .string("2018-12-21"), value: 124.95), + LineData(time: .string("2018-12-24"), value: 124.06), + LineData(time: .string("2018-12-26"), value: 134.18), + LineData(time: .string("2018-12-27"), value: 134.52), + LineData(time: .string("2018-12-28"), value: 133.20), + LineData(time: .string("2018-12-31"), value: 131.09), + LineData(time: .string("2019-01-02"), value: 135.68), + LineData(time: .string("2019-01-03"), value: 131.74), + LineData(time: .string("2019-01-04"), value: 137.95), + LineData(time: .string("2019-01-07"), value: 138.05), + LineData(time: .string("2019-01-08"), value: 142.53), + LineData(time: .string("2019-01-09"), value: 144.23), + LineData(time: .string("2019-01-10"), value: 144.20), + LineData(time: .string("2019-01-11"), value: 143.80), + LineData(time: .string("2019-01-14"), value: 145.39), + LineData(time: .string("2019-01-15"), value: 148.95), + LineData(time: .string("2019-01-16"), value: 147.54), + LineData(time: .string("2019-01-17"), value: 148.30), + LineData(time: .string("2019-01-18"), value: 150.04), + LineData(time: .string("2019-01-22"), value: 147.57), + LineData(time: .string("2019-01-23"), value: 144.30), + LineData(time: .string("2019-01-24"), value: 145.83), + LineData(time: .string("2019-01-25"), value: 149.01), + LineData(time: .string("2019-01-28"), value: 147.47), + LineData(time: .string("2019-01-29"), value: 144.19), + LineData(time: .string("2019-01-30"), value: 150.42), + LineData(time: .string("2019-01-31"), value: 166.69), + LineData(time: .string("2019-02-01"), value: 165.71), + LineData(time: .string("2019-02-04"), value: 169.25), + LineData(time: .string("2019-02-05"), value: 171.16), + LineData(time: .string("2019-02-06"), value: 170.49), + LineData(time: .string("2019-02-07"), value: 166.38), + LineData(time: .string("2019-02-08"), value: 167.33), + LineData(time: .string("2019-02-11"), value: 165.79), + LineData(time: .string("2019-02-12"), value: 165.04), + LineData(time: .string("2019-02-13"), value: 164.07), + LineData(time: .string("2019-02-14"), value: 163.95), + LineData(time: .string("2019-02-15"), value: 162.50), + LineData(time: .string("2019-02-19"), value: 162.29), + LineData(time: .string("2019-02-20"), value: 162.56), + LineData(time: .string("2019-02-21"), value: 160.04), + LineData(time: .string("2019-02-22"), value: 161.89), + LineData(time: .string("2019-02-25"), value: 164.62), + LineData(time: .string("2019-02-26"), value: 164.13), + LineData(time: .string("2019-02-27"), value: 162.81), + LineData(time: .string("2019-02-28"), value: 161.45), + LineData(time: .string("2019-03-01"), value: 162.28), + LineData(time: .string("2019-03-04"), value: 167.37), + LineData(time: .string("2019-03-05"), value: 171.26), + LineData(time: .string("2019-03-06"), value: 172.51), + LineData(time: .string("2019-03-07"), value: 169.13), + LineData(time: .string("2019-03-08"), value: 169.60), + LineData(time: .string("2019-03-11"), value: 172.07), + LineData(time: .string("2019-03-12"), value: 171.92), + LineData(time: .string("2019-03-13"), value: 173.37), + LineData(time: .string("2019-03-14"), value: 170.17), + LineData(time: .string("2019-03-15"), value: 165.98), + LineData(time: .string("2019-03-18"), value: 160.47), + LineData(time: .string("2019-03-19"), value: 161.57), + LineData(time: .string("2019-03-20"), value: 165.44), + LineData(time: .string("2019-03-21"), value: 166.08), + LineData(time: .string("2019-03-22"), value: 164.34), + LineData(time: .string("2019-03-25"), value: 166.29), + LineData(time: .string("2019-03-26"), value: 167.68), + LineData(time: .string("2019-03-27"), value: 165.87), + LineData(time: .string("2019-03-28"), value: 165.55), + LineData(time: .string("2019-03-29"), value: 166.69), + LineData(time: .string("2019-04-01"), value: 168.70), + LineData(time: .string("2019-04-02"), value: 174.20), + LineData(time: .string("2019-04-03"), value: 173.54), + LineData(time: .string("2019-04-04"), value: 176.02), + LineData(time: .string("2019-04-05"), value: 175.72), + LineData(time: .string("2019-04-08"), value: 174.93), + LineData(time: .string("2019-04-09"), value: 177.58), + LineData(time: .string("2019-04-10"), value: 177.82), + LineData(time: .string("2019-04-11"), value: 177.51), + LineData(time: .string("2019-04-12"), value: 179.10), + LineData(time: .string("2019-04-15"), value: 179.65), + LineData(time: .string("2019-04-16"), value: 178.87), + LineData(time: .string("2019-04-17"), value: 178.78), + LineData(time: .string("2019-04-18"), value: 178.28), + LineData(time: .string("2019-04-22"), value: 181.44), + LineData(time: .string("2019-04-23"), value: 183.78), + LineData(time: .string("2019-04-24"), value: 182.58), + LineData(time: .string("2019-04-25"), value: 193.26), + LineData(time: .string("2019-04-26"), value: 191.49), + LineData(time: .string("2019-04-29"), value: 194.78), + LineData(time: .string("2019-04-30"), value: 193.40), + LineData(time: .string("2019-05-01"), value: 193.03), + LineData(time: .string("2019-05-02"), value: 192.53), + LineData(time: .string("2019-05-03"), value: 195.47), + LineData(time: .string("2019-05-06"), value: 193.88), + LineData(time: .string("2019-05-07"), value: 189.77), + LineData(time: .string("2019-05-08"), value: 189.54), + LineData(time: .string("2019-05-09"), value: 188.65), + LineData(time: .string("2019-05-10"), value: 188.34), + LineData(time: .string("2019-05-13"), value: 181.54), + LineData(time: .string("2019-05-14"), value: 180.73), + LineData(time: .string("2019-05-15"), value: 186.27), + LineData(time: .string("2019-05-16"), value: 186.99), + LineData(time: .string("2019-05-17"), value: 185.30), + LineData(time: .string("2019-05-20"), value: 182.72), + LineData(time: .string("2019-05-21"), value: 184.82), + LineData(time: .string("2019-05-22"), value: 185.32), + LineData(time: .string("2019-05-23"), value: 180.87), + LineData(time: .string("2019-05-24"), value: 181.06), + LineData(time: .string("2019-05-28"), value: 183.39) + ] + series.setData(data: data) + self.series = series + } + +} diff --git a/ExampleSPM/LightweightCharts/Example/RangeSwitcherViewController.swift b/ExampleSPM/LightweightCharts/Example/RangeSwitcherViewController.swift new file mode 100644 index 0000000..5d9575e --- /dev/null +++ b/ExampleSPM/LightweightCharts/Example/RangeSwitcherViewController.swift @@ -0,0 +1,598 @@ +import UIKit +import LightweightCharts + +class RangeSwitcherViewController: UIViewController { + + enum Interval: CaseIterable { + case day + case week + case month + case year + + var title: String { + switch self { + case .day: return "1D" + case .week: return "1W" + case .month: return "1M" + case .year: return "1Y" + } + } + + var data: [LineData] { + switch self { + case .day: return Self.dayData + case .week: return Self.weekData + case .month: return Self.monthData + case .year: return Self.yearData + } + } + } + + private var chart: LightweightCharts! + private var series: AreaSeries? + + private let intervals = ["1D", "1W", "1M", "1Y"] + + override func viewDidLoad() { + super.viewDidLoad() + if #available(iOS 13.0, *) { + view.backgroundColor = .systemBackground + } else { + view.backgroundColor = .white + } + + setupUI() + syncToInterval(.day) + } + + private func setupUI() { + let segmentedControl = UISegmentedControl(items: Interval.allCases.map { $0.title }) + segmentedControl.addTarget(self, action: #selector(valueChanged), for: .valueChanged) + view.addSubview(segmentedControl) + segmentedControl.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + segmentedControl.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor), + segmentedControl.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + ]) + } else { + NSLayoutConstraint.activate([ + segmentedControl.centerXAnchor.constraint(equalTo: view.centerXAnchor), + segmentedControl.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } + + let options = ChartOptions( + layout: LayoutOptions(backgroundColor: "#000000", textColor: "#d1d4dc"), + rightPriceScale: VisiblePriceScaleOptions(borderVisible: false), + timeScale: TimeScaleOptions(borderVisible: false), + crosshair: CrosshairOptions(horzLine: CrosshairLineOptions(visible: false)), + grid: GridOptions( + verticalLines: GridLineOptions(visible: false), + horizontalLines: GridLineOptions(color: "rgba(42, 46, 57, 0.5)") + ) + ) + let chart = LightweightCharts(options: options) + view.addSubview(chart) + chart.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + chart.bottomAnchor.constraint(equalTo: segmentedControl.topAnchor, constant: -16) + ]) + } else { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.topAnchor), + chart.bottomAnchor.constraint(equalTo: segmentedControl.topAnchor, constant: -16) + ]) + } + self.chart = chart + + segmentedControl.selectedSegmentIndex = 0 + } + + private func syncToInterval(_ interval: Interval) { + if let series = series { + chart.removeSeries(seriesApi: series) + } + + let options = AreaSeriesOptions( + topColor: "rgba(76, 175, 80, 0.56)", + bottomColor: "rgba(76, 175, 80, 0.04)", + lineColor: "rgba(76, 175, 80, 1)", + lineWidth: .two + ) + series = chart.addAreaSeries(options: options) + series?.setData(data: interval.data) + } + + @objc private func valueChanged(_ sender: UISegmentedControl) { + let interval = Interval.allCases[sender.selectedSegmentIndex] + syncToInterval(interval) + } + +} + +extension RangeSwitcherViewController.Interval { + + private static let dayData = [ + LineData(time: .string("2018-10-19"), value: 26.19), + LineData(time: .string("2018-10-22"), value: 25.87), + LineData(time: .string("2018-10-23"), value: 25.83), + LineData(time: .string("2018-10-24"), value: 25.78), + LineData(time: .string("2018-10-25"), value: 25.82), + LineData(time: .string("2018-10-26"), value: 25.81), + LineData(time: .string("2018-10-29"), value: 25.82), + LineData(time: .string("2018-10-30"), value: 25.71), + LineData(time: .string("2018-10-31"), value: 25.82), + LineData(time: .string("2018-11-01"), value: 25.72), + LineData(time: .string("2018-11-02"), value: 25.74), + LineData(time: .string("2018-11-05"), value: 25.81), + LineData(time: .string("2018-11-06"), value: 25.75), + LineData(time: .string("2018-11-07"), value: 25.73), + LineData(time: .string("2018-11-08"), value: 25.75), + LineData(time: .string("2018-11-09"), value: 25.75), + LineData(time: .string("2018-11-12"), value: 25.76), + LineData(time: .string("2018-11-13"), value: 25.80), + LineData(time: .string("2018-11-14"), value: 25.77), + LineData(time: .string("2018-11-15"), value: 25.75), + LineData(time: .string("2018-11-16"), value: 25.75), + LineData(time: .string("2018-11-19"), value: 25.75), + LineData(time: .string("2018-11-20"), value: 25.72), + LineData(time: .string("2018-11-21"), value: 25.78), + LineData(time: .string("2018-11-23"), value: 25.72), + LineData(time: .string("2018-11-26"), value: 25.78), + LineData(time: .string("2018-11-27"), value: 25.85), + LineData(time: .string("2018-11-28"), value: 25.85), + LineData(time: .string("2018-11-29"), value: 25.55), + LineData(time: .string("2018-11-30"), value: 25.41), + LineData(time: .string("2018-12-03"), value: 25.41), + LineData(time: .string("2018-12-04"), value: 25.42), + LineData(time: .string("2018-12-06"), value: 25.33), + LineData(time: .string("2018-12-07"), value: 25.39), + LineData(time: .string("2018-12-10"), value: 25.32), + LineData(time: .string("2018-12-11"), value: 25.48), + LineData(time: .string("2018-12-12"), value: 25.39), + LineData(time: .string("2018-12-13"), value: 25.45), + LineData(time: .string("2018-12-14"), value: 25.52), + LineData(time: .string("2018-12-17"), value: 25.38), + LineData(time: .string("2018-12-18"), value: 25.36), + LineData(time: .string("2018-12-19"), value: 25.65), + LineData(time: .string("2018-12-20"), value: 25.70), + LineData(time: .string("2018-12-21"), value: 25.66), + LineData(time: .string("2018-12-24"), value: 25.66), + LineData(time: .string("2018-12-26"), value: 25.65), + LineData(time: .string("2018-12-27"), value: 25.66), + LineData(time: .string("2018-12-28"), value: 25.68), + LineData(time: .string("2018-12-31"), value: 25.77), + LineData(time: .string("2019-01-02"), value: 25.72), + LineData(time: .string("2019-01-03"), value: 25.69), + LineData(time: .string("2019-01-04"), value: 25.71), + LineData(time: .string("2019-01-07"), value: 25.72), + LineData(time: .string("2019-01-08"), value: 25.72), + LineData(time: .string("2019-01-09"), value: 25.66), + LineData(time: .string("2019-01-10"), value: 25.85), + LineData(time: .string("2019-01-11"), value: 25.92), + LineData(time: .string("2019-01-14"), value: 25.94), + LineData(time: .string("2019-01-15"), value: 25.95), + LineData(time: .string("2019-01-16"), value: 26.00), + LineData(time: .string("2019-01-17"), value: 25.99), + LineData(time: .string("2019-01-18"), value: 25.60), + LineData(time: .string("2019-01-22"), value: 25.81), + LineData(time: .string("2019-01-23"), value: 25.70), + LineData(time: .string("2019-01-24"), value: 25.74), + LineData(time: .string("2019-01-25"), value: 25.80), + LineData(time: .string("2019-01-28"), value: 25.83), + LineData(time: .string("2019-01-29"), value: 25.70), + LineData(time: .string("2019-01-30"), value: 25.78), + LineData(time: .string("2019-01-31"), value: 25.35), + LineData(time: .string("2019-02-01"), value: 25.60), + LineData(time: .string("2019-02-04"), value: 25.65), + LineData(time: .string("2019-02-05"), value: 25.73), + LineData(time: .string("2019-02-06"), value: 25.71), + LineData(time: .string("2019-02-07"), value: 25.71), + LineData(time: .string("2019-02-08"), value: 25.72), + LineData(time: .string("2019-02-11"), value: 25.76), + LineData(time: .string("2019-02-12"), value: 25.84), + LineData(time: .string("2019-02-13"), value: 25.85), + LineData(time: .string("2019-02-14"), value: 25.87), + LineData(time: .string("2019-02-15"), value: 25.89), + LineData(time: .string("2019-02-19"), value: 25.90), + LineData(time: .string("2019-02-20"), value: 25.92), + LineData(time: .string("2019-02-21"), value: 25.96), + LineData(time: .string("2019-02-22"), value: 26.00), + LineData(time: .string("2019-02-25"), value: 25.93), + LineData(time: .string("2019-02-26"), value: 25.92), + LineData(time: .string("2019-02-27"), value: 25.67), + LineData(time: .string("2019-02-28"), value: 25.79), + LineData(time: .string("2019-03-01"), value: 25.86), + LineData(time: .string("2019-03-04"), value: 25.94), + LineData(time: .string("2019-03-05"), value: 26.02), + LineData(time: .string("2019-03-06"), value: 25.95), + LineData(time: .string("2019-03-07"), value: 25.89), + LineData(time: .string("2019-03-08"), value: 25.94), + LineData(time: .string("2019-03-11"), value: 25.91), + LineData(time: .string("2019-03-12"), value: 25.92), + LineData(time: .string("2019-03-13"), value: 26.00), + LineData(time: .string("2019-03-14"), value: 26.05), + LineData(time: .string("2019-03-15"), value: 26.11), + LineData(time: .string("2019-03-18"), value: 26.10), + LineData(time: .string("2019-03-19"), value: 25.98), + LineData(time: .string("2019-03-20"), value: 26.11), + LineData(time: .string("2019-03-21"), value: 26.12), + LineData(time: .string("2019-03-22"), value: 25.88), + LineData(time: .string("2019-03-25"), value: 25.85), + LineData(time: .string("2019-03-26"), value: 25.72), + LineData(time: .string("2019-03-27"), value: 25.73), + LineData(time: .string("2019-03-28"), value: 25.80), + LineData(time: .string("2019-03-29"), value: 25.77), + LineData(time: .string("2019-04-01"), value: 26.06), + LineData(time: .string("2019-04-02"), value: 25.93), + LineData(time: .string("2019-04-03"), value: 25.95), + LineData(time: .string("2019-04-04"), value: 26.06), + LineData(time: .string("2019-04-05"), value: 26.16), + LineData(time: .string("2019-04-08"), value: 26.12), + LineData(time: .string("2019-04-09"), value: 26.07), + LineData(time: .string("2019-04-10"), value: 26.13), + LineData(time: .string("2019-04-11"), value: 26.04), + LineData(time: .string("2019-04-12"), value: 26.04), + LineData(time: .string("2019-04-15"), value: 26.05), + LineData(time: .string("2019-04-16"), value: 26.01), + LineData(time: .string("2019-04-17"), value: 26.09), + LineData(time: .string("2019-04-18"), value: 26.00), + LineData(time: .string("2019-04-22"), value: 26.00), + LineData(time: .string("2019-04-23"), value: 26.06), + LineData(time: .string("2019-04-24"), value: 26.00), + LineData(time: .string("2019-04-25"), value: 25.81), + LineData(time: .string("2019-04-26"), value: 25.88), + LineData(time: .string("2019-04-29"), value: 25.91), + LineData(time: .string("2019-04-30"), value: 25.90), + LineData(time: .string("2019-05-01"), value: 26.02), + LineData(time: .string("2019-05-02"), value: 25.97), + LineData(time: .string("2019-05-03"), value: 26.02), + LineData(time: .string("2019-05-06"), value: 26.03), + LineData(time: .string("2019-05-07"), value: 26.04), + LineData(time: .string("2019-05-08"), value: 26.05), + LineData(time: .string("2019-05-09"), value: 26.05), + LineData(time: .string("2019-05-10"), value: 26.08), + LineData(time: .string("2019-05-13"), value: 26.05), + LineData(time: .string("2019-05-14"), value: 26.01), + LineData(time: .string("2019-05-15"), value: 26.03), + LineData(time: .string("2019-05-16"), value: 26.14), + LineData(time: .string("2019-05-17"), value: 26.09), + LineData(time: .string("2019-05-20"), value: 26.01), + LineData(time: .string("2019-05-21"), value: 26.12), + LineData(time: .string("2019-05-22"), value: 26.15), + LineData(time: .string("2019-05-23"), value: 26.18), + LineData(time: .string("2019-05-24"), value: 26.16), + LineData(time: .string("2019-05-28"), value: 26.23) + ] + + private static let weekData = [ + LineData(time: .string("2016-07-18"), value: 26.10), + LineData(time: .string("2016-07-25"), value: 26.19), + LineData(time: .string("2016-08-01"), value: 26.24), + LineData(time: .string("2016-08-08"), value: 26.22), + LineData(time: .string("2016-08-15"), value: 25.98), + LineData(time: .string("2016-08-22"), value: 25.85), + LineData(time: .string("2016-08-29"), value: 25.98), + LineData(time: .string("2016-09-05"), value: 25.71), + LineData(time: .string("2016-09-12"), value: 25.84), + LineData(time: .string("2016-09-19"), value: 25.89), + LineData(time: .string("2016-09-26"), value: 25.65), + LineData(time: .string("2016-10-03"), value: 25.69), + LineData(time: .string("2016-10-10"), value: 25.67), + LineData(time: .string("2016-10-17"), value: 26.11), + LineData(time: .string("2016-10-24"), value: 25.80), + LineData(time: .string("2016-10-31"), value: 25.70), + LineData(time: .string("2016-11-07"), value: 25.40), + LineData(time: .string("2016-11-14"), value: 25.32), + LineData(time: .string("2016-11-21"), value: 25.48), + LineData(time: .string("2016-11-28"), value: 25.08), + LineData(time: .string("2016-12-05"), value: 25.06), + LineData(time: .string("2016-12-12"), value: 25.11), + LineData(time: .string("2016-12-19"), value: 25.34), + LineData(time: .string("2016-12-26"), value: 25.20), + LineData(time: .string("2017-01-02"), value: 25.33), + LineData(time: .string("2017-01-09"), value: 25.56), + LineData(time: .string("2017-01-16"), value: 25.32), + LineData(time: .string("2017-01-23"), value: 25.71), + LineData(time: .string("2017-01-30"), value: 25.85), + LineData(time: .string("2017-02-06"), value: 25.77), + LineData(time: .string("2017-02-13"), value: 25.94), + LineData(time: .string("2017-02-20"), value: 25.67), + LineData(time: .string("2017-02-27"), value: 25.60), + LineData(time: .string("2017-03-06"), value: 25.54), + LineData(time: .string("2017-03-13"), value: 25.84), + LineData(time: .string("2017-03-20"), value: 25.96), + LineData(time: .string("2017-03-27"), value: 25.90), + LineData(time: .string("2017-04-03"), value: 25.97), + LineData(time: .string("2017-04-10"), value: 26.00), + LineData(time: .string("2017-04-17"), value: 26.13), + LineData(time: .string("2017-04-24"), value: 26.02), + LineData(time: .string("2017-05-01"), value: 26.30), + LineData(time: .string("2017-05-08"), value: 26.27), + LineData(time: .string("2017-05-15"), value: 26.24), + LineData(time: .string("2017-05-22"), value: 26.02), + LineData(time: .string("2017-05-29"), value: 26.20), + LineData(time: .string("2017-06-05"), value: 26.12), + LineData(time: .string("2017-06-12"), value: 26.20), + LineData(time: .string("2017-06-19"), value: 26.46), + LineData(time: .string("2017-06-26"), value: 26.39), + LineData(time: .string("2017-07-03"), value: 26.52), + LineData(time: .string("2017-07-10"), value: 26.57), + LineData(time: .string("2017-07-17"), value: 26.65), + LineData(time: .string("2017-07-24"), value: 26.45), + LineData(time: .string("2017-07-31"), value: 26.37), + LineData(time: .string("2017-08-07"), value: 26.13), + LineData(time: .string("2017-08-14"), value: 26.21), + LineData(time: .string("2017-08-21"), value: 26.31), + LineData(time: .string("2017-08-28"), value: 26.33), + LineData(time: .string("2017-09-04"), value: 26.38), + LineData(time: .string("2017-09-11"), value: 26.38), + LineData(time: .string("2017-09-18"), value: 26.50), + LineData(time: .string("2017-09-25"), value: 26.39), + LineData(time: .string("2017-10-02"), value: 25.95), + LineData(time: .string("2017-10-09"), value: 26.15), + LineData(time: .string("2017-10-16"), value: 26.43), + LineData(time: .string("2017-10-23"), value: 26.22), + LineData(time: .string("2017-10-30"), value: 26.14), + LineData(time: .string("2017-11-06"), value: 26.08), + LineData(time: .string("2017-11-13"), value: 26.27), + LineData(time: .string("2017-11-20"), value: 26.30), + LineData(time: .string("2017-11-27"), value: 25.92), + LineData(time: .string("2017-12-04"), value: 26.10), + LineData(time: .string("2017-12-11"), value: 25.88), + LineData(time: .string("2017-12-18"), value: 25.82), + LineData(time: .string("2017-12-25"), value: 25.82), + LineData(time: .string("2018-01-01"), value: 25.81), + LineData(time: .string("2018-01-08"), value: 25.95), + LineData(time: .string("2018-01-15"), value: 26.03), + LineData(time: .string("2018-01-22"), value: 26.04), + LineData(time: .string("2018-01-29"), value: 25.96), + LineData(time: .string("2018-02-05"), value: 25.99), + LineData(time: .string("2018-02-12"), value: 26.00), + LineData(time: .string("2018-02-19"), value: 26.06), + LineData(time: .string("2018-02-26"), value: 25.77), + LineData(time: .string("2018-03-05"), value: 25.81), + LineData(time: .string("2018-03-12"), value: 25.88), + LineData(time: .string("2018-03-19"), value: 25.72), + LineData(time: .string("2018-03-26"), value: 25.75), + LineData(time: .string("2018-04-02"), value: 25.70), + LineData(time: .string("2018-04-09"), value: 25.73), + LineData(time: .string("2018-04-16"), value: 25.74), + LineData(time: .string("2018-04-23"), value: 25.69), + LineData(time: .string("2018-04-30"), value: 25.76), + LineData(time: .string("2018-05-07"), value: 25.89), + LineData(time: .string("2018-05-14"), value: 25.89), + LineData(time: .string("2018-05-21"), value: 26.00), + LineData(time: .string("2018-05-28"), value: 25.79), + LineData(time: .string("2018-06-04"), value: 26.11), + LineData(time: .string("2018-06-11"), value: 26.43), + LineData(time: .string("2018-06-18"), value: 26.30), + LineData(time: .string("2018-06-25"), value: 26.58), + LineData(time: .string("2018-07-02"), value: 26.33), + LineData(time: .string("2018-07-09"), value: 26.33), + LineData(time: .string("2018-07-16"), value: 26.32), + LineData(time: .string("2018-07-23"), value: 26.20), + LineData(time: .string("2018-07-30"), value: 26.03), + LineData(time: .string("2018-08-06"), value: 26.15), + LineData(time: .string("2018-08-13"), value: 26.17), + LineData(time: .string("2018-08-20"), value: 26.28), + LineData(time: .string("2018-08-27"), value: 25.86), + LineData(time: .string("2018-09-03"), value: 25.69), + LineData(time: .string("2018-09-10"), value: 25.69), + LineData(time: .string("2018-09-17"), value: 25.64), + LineData(time: .string("2018-09-24"), value: 25.67), + LineData(time: .string("2018-10-01"), value: 25.55), + LineData(time: .string("2018-10-08"), value: 25.59), + LineData(time: .string("2018-10-15"), value: 26.19), + LineData(time: .string("2018-10-22"), value: 25.81), + LineData(time: .string("2018-10-29"), value: 25.74), + LineData(time: .string("2018-11-05"), value: 25.75), + LineData(time: .string("2018-11-12"), value: 25.75), + LineData(time: .string("2018-11-19"), value: 25.72), + LineData(time: .string("2018-11-26"), value: 25.41), + LineData(time: .string("2018-12-03"), value: 25.39), + LineData(time: .string("2018-12-10"), value: 25.52), + LineData(time: .string("2018-12-17"), value: 25.66), + LineData(time: .string("2018-12-24"), value: 25.68), + LineData(time: .string("2018-12-31"), value: 25.71), + LineData(time: .string("2019-01-07"), value: 25.92), + LineData(time: .string("2019-01-14"), value: 25.60), + LineData(time: .string("2019-01-21"), value: 25.80), + LineData(time: .string("2019-01-28"), value: 25.60), + LineData(time: .string("2019-02-04"), value: 25.72), + LineData(time: .string("2019-02-11"), value: 25.89), + LineData(time: .string("2019-02-18"), value: 26.00), + LineData(time: .string("2019-02-25"), value: 25.86), + LineData(time: .string("2019-03-04"), value: 25.94), + LineData(time: .string("2019-03-11"), value: 26.11), + LineData(time: .string("2019-03-18"), value: 25.88), + LineData(time: .string("2019-03-25"), value: 25.77), + LineData(time: .string("2019-04-01"), value: 26.16), + LineData(time: .string("2019-04-08"), value: 26.04), + LineData(time: .string("2019-04-15"), value: 26.00), + LineData(time: .string("2019-04-22"), value: 25.88), + LineData(time: .string("2019-04-29"), value: 26.02), + LineData(time: .string("2019-05-06"), value: 26.08), + LineData(time: .string("2019-05-13"), value: 26.09), + LineData(time: .string("2019-05-20"), value: 26.16), + LineData(time: .string("2019-05-27"), value: 26.23) + ] + + private static let monthData = [ + LineData(time: .string("2006-12-01"), value: 25.40), + LineData(time: .string("2007-01-01"), value: 25.50), + LineData(time: .string("2007-02-01"), value: 25.11), + LineData(time: .string("2007-03-01"), value: 25.24), + LineData(time: .string("2007-04-02"), value: 25.34), + LineData(time: .string("2007-05-01"), value: 24.82), + LineData(time: .string("2007-06-01"), value: 23.85), + LineData(time: .string("2007-07-02"), value: 23.24), + LineData(time: .string("2007-08-01"), value: 23.05), + LineData(time: .string("2007-09-03"), value: 22.26), + LineData(time: .string("2007-10-01"), value: 22.52), + LineData(time: .string("2007-11-01"), value: 20.84), + LineData(time: .string("2007-12-03"), value: 20.37), + LineData(time: .string("2008-01-01"), value: 23.90), + LineData(time: .string("2008-02-01"), value: 22.58), + LineData(time: .string("2008-03-03"), value: 21.74), + LineData(time: .string("2008-04-01"), value: 22.50), + LineData(time: .string("2008-05-01"), value: 22.38), + LineData(time: .string("2008-06-02"), value: 20.58), + LineData(time: .string("2008-07-01"), value: 20.60), + LineData(time: .string("2008-08-01"), value: 20.82), + LineData(time: .string("2008-09-01"), value: 17.50), + LineData(time: .string("2008-10-01"), value: 17.70), + LineData(time: .string("2008-11-03"), value: 15.52), + LineData(time: .string("2008-12-01"), value: 18.58), + LineData(time: .string("2009-01-01"), value: 15.40), + LineData(time: .string("2009-02-02"), value: 11.68), + LineData(time: .string("2009-03-02"), value: 14.89), + LineData(time: .string("2009-04-01"), value: 16.24), + LineData(time: .string("2009-05-01"), value: 18.33), + LineData(time: .string("2009-06-01"), value: 18.08), + LineData(time: .string("2009-07-01"), value: 20.07), + LineData(time: .string("2009-08-03"), value: 20.35), + LineData(time: .string("2009-09-01"), value: 21.53), + LineData(time: .string("2009-10-01"), value: 21.48), + LineData(time: .string("2009-11-02"), value: 20.28), + LineData(time: .string("2009-12-01"), value: 21.39), + LineData(time: .string("2010-01-01"), value: 22.00), + LineData(time: .string("2010-02-01"), value: 22.31), + LineData(time: .string("2010-03-01"), value: 22.82), + LineData(time: .string("2010-04-01"), value: 22.58), + LineData(time: .string("2010-05-03"), value: 21.02), + LineData(time: .string("2010-06-01"), value: 21.45), + LineData(time: .string("2010-07-01"), value: 22.42), + LineData(time: .string("2010-08-02"), value: 23.61), + LineData(time: .string("2010-09-01"), value: 24.40), + LineData(time: .string("2010-10-01"), value: 24.46), + LineData(time: .string("2010-11-01"), value: 23.64), + LineData(time: .string("2010-12-01"), value: 22.90), + LineData(time: .string("2011-01-03"), value: 23.73), + LineData(time: .string("2011-02-01"), value: 23.52), + LineData(time: .string("2011-03-01"), value: 24.15), + LineData(time: .string("2011-04-01"), value: 24.37), + LineData(time: .string("2011-05-02"), value: 24.40), + LineData(time: .string("2011-06-01"), value: 24.45), + LineData(time: .string("2011-07-01"), value: 24.24), + LineData(time: .string("2011-08-01"), value: 24.00), + LineData(time: .string("2011-09-01"), value: 22.77), + LineData(time: .string("2011-10-03"), value: 24.21), + LineData(time: .string("2011-11-01"), value: 23.40), + LineData(time: .string("2011-12-01"), value: 23.90), + LineData(time: .string("2012-01-02"), value: 24.84), + LineData(time: .string("2012-02-01"), value: 25.04), + LineData(time: .string("2012-03-01"), value: 24.90), + LineData(time: .string("2012-04-02"), value: 25.06), + LineData(time: .string("2012-05-01"), value: 24.63), + LineData(time: .string("2012-06-01"), value: 25.07), + LineData(time: .string("2012-07-02"), value: 25.30), + LineData(time: .string("2012-08-01"), value: 25.08), + LineData(time: .string("2012-09-03"), value: 25.27), + LineData(time: .string("2012-10-01"), value: 25.39), + LineData(time: .string("2012-11-01"), value: 25.06), + LineData(time: .string("2012-12-03"), value: 25.03), + LineData(time: .string("2013-01-01"), value: 25.26), + LineData(time: .string("2013-02-01"), value: 25.20), + LineData(time: .string("2013-03-01"), value: 25.30), + LineData(time: .string("2013-04-01"), value: 25.38), + LineData(time: .string("2013-05-01"), value: 25.22), + LineData(time: .string("2013-06-03"), value: 24.88), + LineData(time: .string("2013-07-01"), value: 24.98), + LineData(time: .string("2013-08-01"), value: 24.60), + LineData(time: .string("2013-09-02"), value: 24.65), + LineData(time: .string("2013-10-01"), value: 24.62), + LineData(time: .string("2013-11-01"), value: 24.65), + LineData(time: .string("2013-12-02"), value: 24.70), + LineData(time: .string("2014-01-01"), value: 24.98), + LineData(time: .string("2014-02-03"), value: 24.95), + LineData(time: .string("2014-03-03"), value: 25.45), + LineData(time: .string("2014-04-01"), value: 25.40), + LineData(time: .string("2014-05-01"), value: 25.51), + LineData(time: .string("2014-06-02"), value: 25.34), + LineData(time: .string("2014-07-01"), value: 25.30), + LineData(time: .string("2014-08-01"), value: 25.36), + LineData(time: .string("2014-09-01"), value: 25.16), + LineData(time: .string("2014-10-01"), value: 25.53), + LineData(time: .string("2014-11-03"), value: 25.40), + LineData(time: .string("2014-12-01"), value: 25.70), + LineData(time: .string("2015-01-01"), value: 25.95), + LineData(time: .string("2015-02-02"), value: 25.81), + LineData(time: .string("2015-03-02"), value: 25.63), + LineData(time: .string("2015-04-01"), value: 25.39), + LineData(time: .string("2015-05-01"), value: 25.62), + LineData(time: .string("2015-06-01"), value: 25.23), + LineData(time: .string("2015-07-01"), value: 25.47), + LineData(time: .string("2015-08-03"), value: 25.18), + LineData(time: .string("2015-09-01"), value: 25.30), + LineData(time: .string("2015-10-01"), value: 25.68), + LineData(time: .string("2015-11-02"), value: 25.63), + LineData(time: .string("2015-12-01"), value: 25.57), + LineData(time: .string("2016-01-01"), value: 25.55), + LineData(time: .string("2016-02-01"), value: 25.05), + LineData(time: .string("2016-03-01"), value: 25.61), + LineData(time: .string("2016-04-01"), value: 25.91), + LineData(time: .string("2016-05-02"), value: 25.84), + LineData(time: .string("2016-06-01"), value: 25.94), + LineData(time: .string("2016-07-01"), value: 26.19), + LineData(time: .string("2016-08-01"), value: 26.06), + LineData(time: .string("2016-09-01"), value: 25.65), + LineData(time: .string("2016-10-03"), value: 25.80), + LineData(time: .string("2016-11-01"), value: 25.06), + LineData(time: .string("2016-12-01"), value: 25.20), + LineData(time: .string("2017-01-02"), value: 25.70), + LineData(time: .string("2017-02-01"), value: 25.78), + LineData(time: .string("2017-03-01"), value: 25.90), + LineData(time: .string("2017-04-03"), value: 26.02), + LineData(time: .string("2017-05-01"), value: 26.02), + LineData(time: .string("2017-06-01"), value: 26.39), + LineData(time: .string("2017-07-03"), value: 26.30), + LineData(time: .string("2017-08-01"), value: 26.14), + LineData(time: .string("2017-09-01"), value: 26.39), + LineData(time: .string("2017-10-02"), value: 26.12), + LineData(time: .string("2017-11-01"), value: 25.81), + LineData(time: .string("2017-12-01"), value: 25.82), + LineData(time: .string("2018-01-01"), value: 26.06), + LineData(time: .string("2018-02-01"), value: 25.78), + LineData(time: .string("2018-03-01"), value: 25.75), + LineData(time: .string("2018-04-02"), value: 25.72), + LineData(time: .string("2018-05-01"), value: 25.75), + LineData(time: .string("2018-06-01"), value: 26.58), + LineData(time: .string("2018-07-02"), value: 26.14), + LineData(time: .string("2018-08-01"), value: 25.86), + LineData(time: .string("2018-09-03"), value: 25.67), + LineData(time: .string("2018-10-01"), value: 25.82), + LineData(time: .string("2018-11-01"), value: 25.41), + LineData(time: .string("2018-12-03"), value: 25.77), + LineData(time: .string("2019-01-01"), value: 25.35), + LineData(time: .string("2019-02-01"), value: 25.79), + LineData(time: .string("2019-03-01"), value: 25.77), + LineData(time: .string("2019-04-01"), value: 25.90), + LineData(time: .string("2019-05-01"), value: 26.23) + ] + + private static let yearData = [ + LineData(time: .string("2006-01-02"), value: 24.89), + LineData(time: .string("2007-01-01"), value: 25.50), + LineData(time: .string("2008-01-01"), value: 23.90), + LineData(time: .string("2009-01-01"), value: 15.40), + LineData(time: .string("2010-01-01"), value: 22.00), + LineData(time: .string("2011-01-03"), value: 23.73), + LineData(time: .string("2012-01-02"), value: 24.84), + LineData(time: .string("2013-01-01"), value: 25.26), + LineData(time: .string("2014-01-01"), value: 24.98), + LineData(time: .string("2015-01-01"), value: 25.95), + LineData(time: .string("2016-01-01"), value: 25.55), + LineData(time: .string("2017-01-02"), value: 25.70), + LineData(time: .string("2018-01-01"), value: 26.06), + LineData(time: .string("2019-01-01"), value: 26.23) + ] + +} diff --git a/ExampleSPM/LightweightCharts/Example/RealtimeEmulationViewController.swift b/ExampleSPM/LightweightCharts/Example/RealtimeEmulationViewController.swift new file mode 100644 index 0000000..87a0e7b --- /dev/null +++ b/ExampleSPM/LightweightCharts/Example/RealtimeEmulationViewController.swift @@ -0,0 +1,305 @@ +import UIKit +import LightweightCharts + +class RealtimeEmulationViewController: UIViewController { + + private var chart: LightweightCharts! + private var series: CandlestickSeries! + private var data = [ + BarData(time: .string("2018-10-19"), open: 54.62, high: 55.50, low: 54.52, close: 54.90), + BarData(time: .string("2018-10-22"), open: 55.08, high: 55.27, low: 54.61, close: 54.98), + BarData(time: .string("2018-10-23"), open: 56.09, high: 57.47, low: 56.09, close: 57.21), + BarData(time: .string("2018-10-24"), open: 57.00, high: 58.44, low: 56.41, close: 57.42), + BarData(time: .string("2018-10-25"), open: 57.46, high: 57.63, low: 56.17, close: 56.43), + BarData(time: .string("2018-10-26"), open: 56.26, high: 56.62, low: 55.19, close: 55.51), + BarData(time: .string("2018-10-29"), open: 55.81, high: 57.15, low: 55.72, close: 56.48), + BarData(time: .string("2018-10-30"), open: 56.92, high: 58.80, low: 56.92, close: 58.18), + BarData(time: .string("2018-10-31"), open: 58.32, high: 58.32, low: 56.76, close: 57.09), + BarData(time: .string("2018-11-01"), open: 56.98, high: 57.28, low: 55.55, close: 56.05), + BarData(time: .string("2018-11-02"), open: 56.34, high: 57.08, low: 55.92, close: 56.63), + BarData(time: .string("2018-11-05"), open: 56.51, high: 57.45, low: 56.51, close: 57.21), + BarData(time: .string("2018-11-06"), open: 57.02, high: 57.35, low: 56.65, close: 57.21), + BarData(time: .string("2018-11-07"), open: 57.55, high: 57.78, low: 57.03, close: 57.65), + BarData(time: .string("2018-11-08"), open: 57.70, high: 58.44, low: 57.66, close: 58.27), + BarData(time: .string("2018-11-09"), open: 58.32, high: 59.20, low: 57.94, close: 58.46), + BarData(time: .string("2018-11-12"), open: 58.84, high: 59.40, low: 58.54, close: 58.72), + BarData(time: .string("2018-11-13"), open: 59.09, high: 59.14, low: 58.32, close: 58.66), + BarData(time: .string("2018-11-14"), open: 59.13, high: 59.32, low: 58.41, close: 58.94), + BarData(time: .string("2018-11-15"), open: 58.85, high: 59.09, low: 58.45, close: 59.08), + BarData(time: .string("2018-11-16"), open: 59.06, high: 60.39, low: 58.91, close: 60.21), + BarData(time: .string("2018-11-19"), open: 60.25, high: 61.32, low: 60.18, close: 60.62), + BarData(time: .string("2018-11-20"), open: 61.03, high: 61.58, low: 59.17, close: 59.46), + BarData(time: .string("2018-11-21"), open: 59.26, high: 59.90, low: 58.88, close: 59.16), + BarData(time: .string("2018-11-23"), open: 58.86, high: 59.00, low: 58.29, close: 58.64), + BarData(time: .string("2018-11-26"), open: 58.64, high: 59.51, low: 58.31, close: 59.17), + BarData(time: .string("2018-11-27"), open: 59.21, high: 60.70, low: 59.18, close: 60.65), + BarData(time: .string("2018-11-28"), open: 60.70, high: 60.73, low: 59.64, close: 60.06), + BarData(time: .string("2018-11-29"), open: 59.42, high: 59.79, low: 59.26, close: 59.45), + BarData(time: .string("2018-11-30"), open: 59.57, high: 60.37, low: 59.48, close: 60.30), + BarData(time: .string("2018-12-03"), open: 59.50, high: 59.75, low: 57.69, close: 58.16), + BarData(time: .string("2018-12-04"), open: 58.10, high: 59.40, low: 57.96, close: 58.09), + BarData(time: .string("2018-12-06"), open: 58.18, high: 58.64, low: 57.16, close: 58.08), + BarData(time: .string("2018-12-07"), open: 57.91, high: 58.43, low: 57.34, close: 57.68), + BarData(time: .string("2018-12-10"), open: 57.80, high: 58.37, low: 56.87, close: 58.27), + BarData(time: .string("2018-12-11"), open: 58.77, high: 59.40, low: 58.63, close: 58.85), + BarData(time: .string("2018-12-12"), open: 57.79, high: 58.19, low: 57.23, close: 57.25), + BarData(time: .string("2018-12-13"), open: 57.00, high: 57.50, low: 56.81, close: 57.09), + BarData(time: .string("2018-12-14"), open: 56.95, high: 57.50, low: 56.75, close: 57.08), + BarData(time: .string("2018-12-17"), open: 57.06, high: 57.31, low: 55.53, close: 55.95), + BarData(time: .string("2018-12-18"), open: 55.94, high: 56.69, low: 55.31, close: 55.65), + BarData(time: .string("2018-12-19"), open: 55.72, high: 56.92, low: 55.50, close: 55.86), + BarData(time: .string("2018-12-20"), open: 55.92, high: 56.01, low: 54.26, close: 55.07), + BarData(time: .string("2018-12-21"), open: 54.84, high: 56.53, low: 54.24, close: 54.92), + BarData(time: .string("2018-12-24"), open: 54.68, high: 55.04, low: 52.94, close: 53.05), + BarData(time: .string("2018-12-26"), open: 53.23, high: 54.47, low: 52.40, close: 54.44), + BarData(time: .string("2018-12-27"), open: 54.31, high: 55.17, low: 53.35, close: 55.15), + BarData(time: .string("2018-12-28"), open: 55.37, high: 55.86, low: 54.90, close: 55.27), + BarData(time: .string("2018-12-31"), open: 55.53, high: 56.23, low: 55.07, close: 56.22), + BarData(time: .string("2019-01-02"), open: 56.16, high: 56.16, low: 55.28, close: 56.02), + BarData(time: .string("2019-01-03"), open: 56.30, high: 56.99, low: 56.06, close: 56.22), + BarData(time: .string("2019-01-04"), open: 56.49, high: 56.89, low: 55.95, close: 56.36), + BarData(time: .string("2019-01-07"), open: 56.76, high: 57.26, low: 56.55, close: 56.72), + BarData(time: .string("2019-01-08"), open: 57.27, high: 58.69, low: 57.05, close: 58.38), + BarData(time: .string("2019-01-09"), open: 57.68, high: 57.72, low: 56.85, close: 57.05), + BarData(time: .string("2019-01-10"), open: 57.29, high: 57.70, low: 56.87, close: 57.60), + BarData(time: .string("2019-01-11"), open: 57.84, high: 58.26, low: 57.42, close: 58.02), + BarData(time: .string("2019-01-14"), open: 57.83, high: 58.15, low: 57.67, close: 58.03), + BarData(time: .string("2019-01-15"), open: 57.74, high: 58.29, low: 57.58, close: 58.10), + BarData(time: .string("2019-01-16"), open: 57.93, high: 57.93, low: 57.00, close: 57.08), + BarData(time: .string("2019-01-17"), open: 57.16, high: 57.40, low: 56.21, close: 56.83), + BarData(time: .string("2019-01-18"), open: 56.92, high: 57.47, low: 56.84, close: 57.09), + BarData(time: .string("2019-01-22"), open: 57.23, high: 57.39, low: 56.40, close: 56.99), + BarData(time: .string("2019-01-23"), open: 56.98, high: 57.87, low: 56.93, close: 57.76), + BarData(time: .string("2019-01-24"), open: 57.61, high: 57.65, low: 56.50, close: 57.07), + BarData(time: .string("2019-01-25"), open: 57.18, high: 57.47, low: 56.23, close: 56.40), + BarData(time: .string("2019-01-28"), open: 56.12, high: 56.22, low: 54.80, close: 55.07), + BarData(time: .string("2019-01-29"), open: 53.62, high: 54.30, low: 52.97, close: 53.28), + BarData(time: .string("2019-01-30"), open: 53.10, high: 54.02, low: 52.28, close: 54.00), + BarData(time: .string("2019-01-31"), open: 54.05, high: 55.19, low: 53.53, close: 55.06), + BarData(time: .string("2019-02-01"), open: 55.21, high: 55.30, low: 54.47, close: 54.55), + BarData(time: .string("2019-02-04"), open: 54.60, high: 54.69, low: 53.67, close: 54.04), + BarData(time: .string("2019-02-05"), open: 54.10, high: 54.34, low: 53.61, close: 54.14), + BarData(time: .string("2019-02-06"), open: 54.11, high: 54.37, low: 53.68, close: 53.79), + BarData(time: .string("2019-02-07"), open: 53.61, high: 53.73, low: 53.02, close: 53.57), + BarData(time: .string("2019-02-08"), open: 53.36, high: 53.96, low: 53.30, close: 53.95), + BarData(time: .string("2019-02-11"), open: 54.13, high: 54.37, low: 53.86, close: 54.05), + BarData(time: .string("2019-02-12"), open: 54.45, high: 54.77, low: 54.19, close: 54.42), + BarData(time: .string("2019-02-13"), open: 54.35, high: 54.77, low: 54.28, close: 54.48), + BarData(time: .string("2019-02-14"), open: 54.38, high: 54.52, low: 53.95, close: 54.03), + BarData(time: .string("2019-02-15"), open: 54.48, high: 55.19, low: 54.32, close: 55.16), + BarData(time: .string("2019-02-19"), open: 55.06, high: 55.66, low: 54.82, close: 55.44), + BarData(time: .string("2019-02-20"), open: 55.37, high: 55.91, low: 55.24, close: 55.76), + BarData(time: .string("2019-02-21"), open: 55.55, high: 56.72, low: 55.46, close: 56.15), + BarData(time: .string("2019-02-22"), open: 56.43, high: 57.13, low: 56.40, close: 56.92), + BarData(time: .string("2019-02-25"), open: 57.00, high: 57.27, low: 56.55, close: 56.78), + BarData(time: .string("2019-02-26"), open: 56.82, high: 57.09, low: 56.46, close: 56.64), + BarData(time: .string("2019-02-27"), open: 56.55, high: 56.73, low: 56.35, close: 56.72), + BarData(time: .string("2019-02-28"), open: 56.74, high: 57.61, low: 56.72, close: 56.92), + BarData(time: .string("2019-03-01"), open: 57.02, high: 57.15, low: 56.35, close: 56.96), + BarData(time: .string("2019-03-04"), open: 57.15, high: 57.34, low: 55.66, close: 56.24), + BarData(time: .string("2019-03-05"), open: 56.09, high: 56.17, low: 55.51, close: 56.08), + BarData(time: .string("2019-03-06"), open: 56.19, high: 56.42, low: 55.45, close: 55.68), + BarData(time: .string("2019-03-07"), open: 55.76, high: 56.40, low: 55.72, close: 56.30), + BarData(time: .string("2019-03-08"), open: 56.36, high: 56.68, low: 56.00, close: 56.53), + BarData(time: .string("2019-03-11"), open: 56.76, high: 57.62, low: 56.75, close: 57.58), + BarData(time: .string("2019-03-12"), open: 57.63, high: 58.11, low: 57.36, close: 57.43), + BarData(time: .string("2019-03-13"), open: 57.37, high: 57.74, low: 57.34, close: 57.66), + BarData(time: .string("2019-03-14"), open: 57.71, high: 58.09, low: 57.51, close: 57.95), + BarData(time: .string("2019-03-15"), open: 58.04, high: 58.51, low: 57.93, close: 58.39), + BarData(time: .string("2019-03-18"), open: 58.27, high: 58.32, low: 57.56, close: 58.07), + BarData(time: .string("2019-03-19"), open: 58.10, high: 58.20, low: 57.31, close: 57.50), + BarData(time: .string("2019-03-20"), open: 57.51, high: 58.05, low: 57.11, close: 57.67), + BarData(time: .string("2019-03-21"), open: 57.58, high: 58.49, low: 57.57, close: 58.29), + BarData(time: .string("2019-03-22"), open: 58.16, high: 60.00, low: 58.13, close: 59.76), + BarData(time: .string("2019-03-25"), open: 59.63, high: 60.19, low: 59.53, close: 60.08), + BarData(time: .string("2019-03-26"), open: 60.30, high: 60.69, low: 60.17, close: 60.63), + BarData(time: .string("2019-03-27"), open: 60.56, high: 61.19, low: 60.48, close: 60.88), + BarData(time: .string("2019-03-28"), open: 60.88, high: 60.89, low: 58.44, close: 59.08), + BarData(time: .string("2019-03-29"), open: 59.20, high: 59.27, low: 58.32, close: 59.13), + BarData(time: .string("2019-04-01"), open: 59.39, high: 59.41, low: 58.79, close: 59.09), + BarData(time: .string("2019-04-02"), open: 59.22, high: 59.23, low: 58.34, close: 58.53), + BarData(time: .string("2019-04-03"), open: 58.78, high: 59.07, low: 58.41, close: 58.87), + BarData(time: .string("2019-04-04"), open: 58.84, high: 59.10, low: 58.77, close: 58.99), + BarData(time: .string("2019-04-05"), open: 59.02, high: 59.09, low: 58.82, close: 59.09), + BarData(time: .string("2019-04-08"), open: 59.02, high: 59.13, low: 58.72, close: 59.13), + BarData(time: .string("2019-04-09"), open: 58.37, high: 58.56, low: 58.04, close: 58.40), + BarData(time: .string("2019-04-10"), open: 58.40, high: 58.70, low: 58.36, close: 58.61), + BarData(time: .string("2019-04-11"), open: 58.65, high: 58.73, low: 58.20, close: 58.56), + BarData(time: .string("2019-04-12"), open: 58.75, high: 58.79, low: 58.52, close: 58.74), + BarData(time: .string("2019-04-15"), open: 58.91, high: 58.95, low: 58.59, close: 58.71), + BarData(time: .string("2019-04-16"), open: 58.79, high: 58.98, low: 58.66, close: 58.79), + BarData(time: .string("2019-04-17"), open: 58.40, high: 58.46, low: 57.64, close: 57.78), + BarData(time: .string("2019-04-18"), open: 57.51, high: 58.20, low: 57.28, close: 58.04), + BarData(time: .string("2019-04-22"), open: 58.14, high: 58.49, low: 57.89, close: 58.37), + BarData(time: .string("2019-04-23"), open: 57.62, high: 57.72, low: 56.30, close: 57.15), + BarData(time: .string("2019-04-24"), open: 57.34, high: 57.57, low: 56.73, close: 57.08), + BarData(time: .string("2019-04-25"), open: 56.82, high: 56.90, low: 55.75, close: 55.85), + BarData(time: .string("2019-04-26"), open: 56.06, high: 56.81, low: 55.83, close: 56.58), + BarData(time: .string("2019-04-29"), open: 56.75, high: 57.17, low: 56.71, close: 56.84), + BarData(time: .string("2019-04-30"), open: 56.99, high: 57.45, low: 56.76, close: 57.19), + BarData(time: .string("2019-05-01"), open: 57.23, high: 57.30, low: 56.52, close: 56.52), + BarData(time: .string("2019-05-02"), open: 56.81, high: 58.23, low: 56.68, close: 56.99), + BarData(time: .string("2019-05-03"), open: 57.15, high: 57.36, low: 56.87, close: 57.24), + BarData(time: .string("2019-05-06"), open: 56.83, high: 57.09, low: 56.74, close: 56.91), + BarData(time: .string("2019-05-07"), open: 56.69, high: 56.81, low: 56.33, close: 56.63), + BarData(time: .string("2019-05-08"), open: 56.66, high: 56.70, low: 56.25, close: 56.38), + BarData(time: .string("2019-05-09"), open: 56.12, high: 56.56, low: 55.93, close: 56.48), + BarData(time: .string("2019-05-10"), open: 56.49, high: 57.04, low: 56.26, close: 56.91), + BarData(time: .string("2019-05-13"), open: 56.72, high: 57.34, low: 56.66, close: 56.75), + BarData(time: .string("2019-05-14"), open: 56.76, high: 57.19, low: 56.50, close: 56.55), + BarData(time: .string("2019-05-15"), open: 56.51, high: 56.84, low: 56.17, close: 56.81), + BarData(time: .string("2019-05-16"), open: 57.00, high: 57.80, low: 56.82, close: 57.38), + BarData(time: .string("2019-05-17"), open: 57.06, high: 58.48, low: 57.01, close: 58.09), + BarData(time: .string("2019-05-20"), open: 59.15, high: 60.54, low: 58.00, close: 59.01), + BarData(time: .string("2019-05-21"), open: 59.10, high: 59.63, low: 58.76, close: 59.50), + BarData(time: .string("2019-05-22"), open: 59.09, high: 59.37, low: 58.96, close: 59.25), + BarData(time: .string("2019-05-23"), open: 59.00, high: 59.27, low: 58.54, close: 58.87), + BarData(time: .string("2019-05-24"), open: 59.07, high: 59.36, low: 58.67, close: 59.32), + BarData(time: .string("2019-05-28"), open: 59.21, high: 59.66, low: 59.02, close: 59.57) + ] + private lazy var lastClose = data.last!.close + private lazy var lastIndex = data.endIndex - 1 + private lazy var targetIndex = lastIndex + 105 + Int((Double.random(in: 0...1) + 30).rounded()) + private lazy var targetPrice = randomPrice + private lazy var currentIndex = lastIndex + 1 + private var ticksInCurrentBar = 0 + private var currentBusinessDay = BusinessDay(year: 2019, month: 5, day: 29) + private lazy var currentBar = BarData(time: .businessDay(currentBusinessDay), open: nil, high: nil, low: nil, close: nil) + + private var randomPrice: Double { + 10 + .random(in: 0...1) * 10000 / 100 + } + + private var timer: Timer? + + deinit { + timer?.invalidate() + } + + override func viewDidLoad() { + super.viewDidLoad() + if #available(iOS 13.0, *) { + view.backgroundColor = .systemBackground + } else { + view.backgroundColor = .white + } + + setupChart() + setupSeries() + startSimulation() + } + + private func setupChart() { + let options = ChartOptions(crosshair: CrosshairOptions(mode: .normal)) + let chart = LightweightCharts(options: options) + view.addSubview(chart) + chart.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + ]) + } else { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } + self.chart = chart + } + + private func setupSeries() { + let series = chart.addCandlestickSeries(options: nil) + self.series = series + } + + private func startSimulation() { + series.setData(data: data) + + timer?.invalidate() + timer = .scheduledTimer(withTimeInterval: 0.2, repeats: true) { [weak self] timer in + guard let self = self else { return } + self.tick() + } + RunLoop.current.add(timer!, forMode: .common) + } + + private func tick() { + let lastClose = self.lastClose ?? 0 + let deltaY = targetPrice - lastClose + let deltaX = targetIndex - lastIndex + let andgle = deltaY / Double(deltaX) + let basePrice = lastClose + Double(currentIndex - lastIndex) * andgle + let noise = 0.1 - .random(in: 0...1) * 0.2 + 1 + let noisedPrice = basePrice * noise + + mergeTickToBar(noisedPrice) + + ticksInCurrentBar += 1 + if ticksInCurrentBar == 5 { + // move to next bar + currentIndex += 1 + currentBusinessDay = nextBusinessDay(currentBusinessDay) + currentBar = BarData(time: .businessDay(currentBusinessDay), open: nil, high: nil, low: nil, close: nil) + ticksInCurrentBar = 0 + if currentIndex == 5000 { + reset() + return + } + if currentIndex == targetIndex { + self.lastClose = noisedPrice + lastIndex = currentIndex + targetIndex = lastIndex + 5 + Int((Double.random(in: 0...1) + 30).rounded()) + targetPrice = randomPrice + } + } + } + + private func mergeTickToBar(_ price: BarPrice) { + if currentBar.open == nil { + currentBar.open = price + currentBar.high = price + currentBar.low = price + currentBar.close = price + } else { + currentBar.close = price + currentBar.high = max(currentBar.high ?? price, price) + currentBar.low = min(currentBar.low ?? price, price) + } + series.update(bar: currentBar) + } + + private func reset() { + series.setData(data: data) + + lastClose = data.last!.close + lastIndex = data.endIndex - 1 + + targetIndex = lastIndex + 5 + Int((Double.random(in: 0...1) + 30).rounded()) + targetPrice = randomPrice + + currentIndex = lastIndex + 1 + currentBusinessDay = BusinessDay(year: 2019, month: 5, day: 29) + ticksInCurrentBar = 0 + } + + func nextBusinessDay(_ time: BusinessDay) -> BusinessDay { + let timeZone = TimeZone(identifier: "UTC")! + let dateComponents = DateComponents( + calendar: .current, + timeZone: timeZone, + year: time.year, + month: time.month - 1, + day: time.day + 1 + ) + let date = Calendar.current.date(from: dateComponents)! + let components = Calendar.current.dateComponents(in: timeZone, from: date) + return BusinessDay(year: components.year!, month: components.month! + 1, day: components.day!) + } + +} + diff --git a/ExampleSPM/LightweightCharts/Example/TableViewController.swift b/ExampleSPM/LightweightCharts/Example/TableViewController.swift new file mode 100644 index 0000000..d304405 --- /dev/null +++ b/ExampleSPM/LightweightCharts/Example/TableViewController.swift @@ -0,0 +1,81 @@ +import UIKit + +class TableViewController: UITableViewController { + + struct Row { + let title: String + let viewController: () -> UIViewController + } + + private var rows: [Row] = [] + + override func viewDidLoad() { + super.viewDidLoad() + + setupInitialState() + fillRows() + } + + private func setupInitialState() { + title = "Lightweight Charts" + navigationController?.navigationBar.isTranslucent = false + self.clearsSelectionOnViewWillAppear = true + tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell") + } + + private func fillRows() { + rows = [ + Row(title: "Bar chart", viewController: { BarChartViewController() }), + Row(title: "Candlestick chart", viewController: { CandlestickChartViewController() }), + Row(title: "Custom font family", viewController: { CustomFontFamilyViewController() }), + Row(title: "Custom price formatter", viewController: { CustomPriceFormatterViewController() }), + Row(title: "Custom locale", viewController: { CustomLocaleViewController() }), + Row(title: "Custom themes", viewController: { CustomThemesViewController() }), + Row(title: "Custom watermark", viewController: { CustomWatermarkViewController() }), + Row(title: "Legend", viewController: { LegendViewController() }), + Row(title: "3-line legend", viewController: { ThreeLineLegendViewController() }), + Row(title: "Fit content", viewController: { FitContentViewController() }), + Row(title: "Floating tooltip", viewController: { FloatingTooltipViewController() }), + Row(title: "Tracking tooltip", viewController: { TrackingTooltipViewController() }), + Row(title: "Magnifier tooltip", viewController: { MagnifierTooltipViewController() }), + Row(title: "Go to realtime button", viewController: { GoToRealtimeButtonViewController() }), + Row(title: "Range switcher", viewController: { RangeSwitcherViewController() }), + Row(title: "Intraday data", viewController: { IntradayDataViewController() }), + Row(title: "Percentage price scale", viewController: { PercentagePriceScaleViewController() }), + Row(title: "Inverted price scale", viewController: { InvertedPriceScaleViewController() }), + Row(title: "Logarithmic price scale", viewController: { LogarithmicPriceScaleViewController() }), + Row(title: "No time scale", viewController: { NoTimeScaleViewController() }), + Row(title: "Price scale at left", viewController: { PriceScaleAtLeftViewController() }), + Row(title: "No price scale", viewController: { NoPriceScaleViewController() }), + Row(title: "Realtime emulation", viewController: { RealtimeEmulationViewController() }), + Row(title: "Volume study", viewController: { VolumeStudyViewController() }), + Row(title: "Markers", viewController: { MarkersViewController() }), + Row(title: "Price line", viewController: { PriceLineViewController() }), + Row(title: "Add and remove price line", viewController: { AddAndRemovePriceLineViewController() }) + ] + } + + // MARK: - Table view data source + + override func numberOfSections(in tableView: UITableView) -> Int { 1 } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + rows.count + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) + let row = rows[indexPath.row] + cell.textLabel?.text = row.title + cell.detailTextLabel?.text = "" + return cell + } + + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + let row = rows[indexPath.row] + let vc = row.viewController() + vc.title = row.title + self.navigationController?.pushViewController(vc, animated: true) + } + +} diff --git a/ExampleSPM/LightweightCharts/Example/ThreeLineLegendViewController.swift b/ExampleSPM/LightweightCharts/Example/ThreeLineLegendViewController.swift new file mode 100644 index 0000000..aed9cc0 --- /dev/null +++ b/ExampleSPM/LightweightCharts/Example/ThreeLineLegendViewController.swift @@ -0,0 +1,448 @@ +import UIKit +import LightweightCharts + +class ThreeLineLegendViewController: UIViewController { + + private var chart: LightweightCharts! + private var series: AreaSeries! + private let legendLabel = UILabel() + private let legend = "AEROSPACE" + private let data = [ + LineData(time: .string("2018-03-28"), value: 21.00), + LineData(time: .string("2018-03-29"), value: 20.80), + LineData(time: .string("2018-03-30"), value: 19.40), + LineData(time: .string("2018-04-02"), value: 18.75), + LineData(time: .string("2018-04-03"), value: 18.75), + LineData(time: .string("2018-04-04"), value: 18.95), + LineData(time: .string("2018-04-05"), value: 16.95), + LineData(time: .string("2018-04-06"), value: 17.70), + LineData(time: .string("2018-04-09"), value: 31.00), + LineData(time: .string("2018-04-10"), value: 30.20), + LineData(time: .string("2018-04-11"), value: 31.50), + LineData(time: .string("2018-04-12"), value: 27.95), + LineData(time: .string("2018-04-13"), value: 30.15), + LineData(time: .string("2018-04-16"), value: 29.60), + LineData(time: .string("2018-04-17"), value: 27.70), + LineData(time: .string("2018-04-18"), value: 21.45), + LineData(time: .string("2018-04-19"), value: 24.05), + LineData(time: .string("2018-04-20"), value: 25.60), + LineData(time: .string("2018-04-23"), value: 26.50), + LineData(time: .string("2018-04-24"), value: 28.40), + LineData(time: .string("2018-04-25"), value: 30.55), + LineData(time: .string("2018-04-26"), value: 29.40), + LineData(time: .string("2018-04-27"), value: 30.70), + LineData(time: .string("2018-04-30"), value: 31.00), + LineData(time: .string("2018-05-02"), value: 27.70), + LineData(time: .string("2018-05-03"), value: 30.80), + LineData(time: .string("2018-05-04"), value: 33.35), + LineData(time: .string("2018-05-07"), value: 33.10), + LineData(time: .string("2018-05-08"), value: 34.60), + LineData(time: .string("2018-05-10"), value: 35.20), + LineData(time: .string("2018-05-11"), value: 37.50), + LineData(time: .string("2018-05-14"), value: 38.85), + LineData(time: .string("2018-05-15"), value: 37.00), + LineData(time: .string("2018-05-16"), value: 37.05), + LineData(time: .string("2018-05-17"), value: 37.05), + LineData(time: .string("2018-05-18"), value: 38.25), + LineData(time: .string("2018-05-21"), value: 38.80), + LineData(time: .string("2018-05-22"), value: 40.00), + LineData(time: .string("2018-05-23"), value: 42.45), + LineData(time: .string("2018-05-24"), value: 42.30), + LineData(time: .string("2018-05-25"), value: 42.80), + LineData(time: .string("2018-05-28"), value: 43.45), + LineData(time: .string("2018-05-29"), value: 43.15), + LineData(time: .string("2018-05-30"), value: 35.15), + LineData(time: .string("2018-05-31"), value: 34.20), + LineData(time: .string("2018-06-01"), value: 35.35), + LineData(time: .string("2018-06-04"), value: 37.90), + LineData(time: .string("2018-06-05"), value: 35.75), + LineData(time: .string("2018-06-06"), value: 33.70), + LineData(time: .string("2018-06-07"), value: 30.00), + LineData(time: .string("2018-06-08"), value: 31.10), + LineData(time: .string("2018-06-11"), value: 32.30), + LineData(time: .string("2018-06-13"), value: 30.95), + LineData(time: .string("2018-06-14"), value: 31.45), + LineData(time: .string("2018-06-15"), value: 34.50), + LineData(time: .string("2018-06-18"), value: 35.35), + LineData(time: .string("2018-06-19"), value: 37.00), + LineData(time: .string("2018-06-20"), value: 34.00), + LineData(time: .string("2018-06-21"), value: 34.45), + LineData(time: .string("2018-06-22"), value: 34.45), + LineData(time: .string("2018-06-25"), value: 34.25), + LineData(time: .string("2018-06-26"), value: 34.35), + LineData(time: .string("2018-06-27"), value: 33.85), + LineData(time: .string("2018-06-28"), value: 35.20), + LineData(time: .string("2018-06-29"), value: 35.20), + LineData(time: .string("2018-07-02"), value: 34.85), + LineData(time: .string("2018-07-03"), value: 31.95), + LineData(time: .string("2018-07-04"), value: 35.00), + LineData(time: .string("2018-07-05"), value: 45.80), + LineData(time: .string("2018-07-06"), value: 45.45), + LineData(time: .string("2018-07-09"), value: 46.70), + LineData(time: .string("2018-07-10"), value: 48.45), + LineData(time: .string("2018-07-11"), value: 50.70), + LineData(time: .string("2018-07-12"), value: 50.20), + LineData(time: .string("2018-07-13"), value: 51.75), + LineData(time: .string("2018-07-16"), value: 52.00), + LineData(time: .string("2018-07-17"), value: 50.75), + LineData(time: .string("2018-07-18"), value: 52.00), + LineData(time: .string("2018-07-19"), value: 54.00), + LineData(time: .string("2018-07-20"), value: 53.55), + LineData(time: .string("2018-07-23"), value: 51.20), + LineData(time: .string("2018-07-24"), value: 52.85), + LineData(time: .string("2018-07-25"), value: 53.70), + LineData(time: .string("2018-07-26"), value: 52.30), + LineData(time: .string("2018-07-27"), value: 52.80), + LineData(time: .string("2018-07-30"), value: 53.30), + LineData(time: .string("2018-07-31"), value: 52.05), + LineData(time: .string("2018-08-01"), value: 54.00), + LineData(time: .string("2018-08-02"), value: 59.00), + LineData(time: .string("2018-08-03"), value: 56.90), + LineData(time: .string("2018-08-06"), value: 60.70), + LineData(time: .string("2018-08-07"), value: 60.75), + LineData(time: .string("2018-08-08"), value: 63.15), + LineData(time: .string("2018-08-09"), value: 65.30), + LineData(time: .string("2018-08-10"), value: 70.00), + LineData(time: .string("2018-08-13"), value: 69.25), + LineData(time: .string("2018-08-14"), value: 67.75), + LineData(time: .string("2018-08-15"), value: 67.60), + LineData(time: .string("2018-08-16"), value: 64.50), + LineData(time: .string("2018-08-17"), value: 66.00), + LineData(time: .string("2018-08-20"), value: 66.05), + LineData(time: .string("2018-08-21"), value: 66.65), + LineData(time: .string("2018-08-22"), value: 66.40), + LineData(time: .string("2018-08-23"), value: 69.35), + LineData(time: .string("2018-08-24"), value: 70.55), + LineData(time: .string("2018-08-27"), value: 68.80), + LineData(time: .string("2018-08-28"), value: 68.45), + LineData(time: .string("2018-08-29"), value: 63.20), + LineData(time: .string("2018-08-30"), value: 59.50), + LineData(time: .string("2018-08-31"), value: 59.50), + LineData(time: .string("2018-09-03"), value: 60.45), + LineData(time: .string("2018-09-04"), value: 62.25), + LineData(time: .string("2018-09-05"), value: 63.50), + LineData(time: .string("2018-09-06"), value: 66.90), + LineData(time: .string("2018-09-07"), value: 66.45), + LineData(time: .string("2018-09-10"), value: 68.50), + LineData(time: .string("2018-09-11"), value: 69.90), + LineData(time: .string("2018-09-12"), value: 67.80), + LineData(time: .string("2018-09-13"), value: 67.90), + LineData(time: .string("2018-09-14"), value: 69.25), + LineData(time: .string("2018-09-17"), value: 68.95), + LineData(time: .string("2018-09-18"), value: 65.85), + LineData(time: .string("2018-09-19"), value: 63.60), + LineData(time: .string("2018-09-20"), value: 64.00), + LineData(time: .string("2018-09-21"), value: 64.00), + LineData(time: .string("2018-09-24"), value: 66.05), + LineData(time: .string("2018-09-25"), value: 68.35), + LineData(time: .string("2018-09-26"), value: 68.30), + LineData(time: .string("2018-09-27"), value: 67.95), + LineData(time: .string("2018-09-28"), value: 68.45), + LineData(time: .string("2018-10-01"), value: 68.80), + LineData(time: .string("2018-10-02"), value: 68.60), + LineData(time: .string("2018-10-03"), value: 67.90), + LineData(time: .string("2018-10-04"), value: 68.60), + LineData(time: .string("2018-10-05"), value: 70.35), + LineData(time: .string("2018-10-08"), value: 72.35), + LineData(time: .string("2018-10-09"), value: 72.90), + LineData(time: .string("2018-10-10"), value: 72.85), + LineData(time: .string("2018-10-11"), value: 74.10), + LineData(time: .string("2018-10-12"), value: 73.00), + LineData(time: .string("2018-10-15"), value: 74.85), + LineData(time: .string("2018-10-16"), value: 76.00), + LineData(time: .string("2018-10-17"), value: 77.00), + LineData(time: .string("2018-10-18"), value: 79.00), + LineData(time: .string("2018-10-19"), value: 79.50), + LineData(time: .string("2018-10-22"), value: 82.60), + LineData(time: .string("2018-10-23"), value: 82.70), + LineData(time: .string("2018-10-24"), value: 82.10), + LineData(time: .string("2018-10-25"), value: 83.15), + LineData(time: .string("2018-10-26"), value: 83.40), + LineData(time: .string("2018-10-29"), value: 80.95), + LineData(time: .string("2018-10-30"), value: 76.75), + LineData(time: .string("2018-10-31"), value: 77.75), + LineData(time: .string("2018-11-01"), value: 78.12), + LineData(time: .string("2018-11-02"), value: 73.22), + LineData(time: .string("2018-11-06"), value: 72.60), + LineData(time: .string("2018-11-07"), value: 74.40), + LineData(time: .string("2018-11-08"), value: 76.50), + LineData(time: .string("2018-11-09"), value: 79.86), + LineData(time: .string("2018-11-12"), value: 78.10), + LineData(time: .string("2018-11-13"), value: 77.60), + LineData(time: .string("2018-11-14"), value: 71.70), + LineData(time: .string("2018-11-15"), value: 72.26), + LineData(time: .string("2018-11-16"), value: 73.80), + LineData(time: .string("2018-11-19"), value: 76.28), + LineData(time: .string("2018-11-20"), value: 72.80), + LineData(time: .string("2018-11-21"), value: 66.20), + LineData(time: .string("2018-11-22"), value: 65.10), + LineData(time: .string("2018-11-23"), value: 61.26), + LineData(time: .string("2018-11-26"), value: 64.10), + LineData(time: .string("2018-11-27"), value: 61.72), + LineData(time: .string("2018-11-28"), value: 61.40), + LineData(time: .string("2018-11-29"), value: 61.86), + LineData(time: .string("2018-11-30"), value: 60.60), + LineData(time: .string("2018-12-03"), value: 63.16), + LineData(time: .string("2018-12-04"), value: 68.30), + LineData(time: .string("2018-12-05"), value: 67.20), + LineData(time: .string("2018-12-06"), value: 68.56), + LineData(time: .string("2018-12-07"), value: 71.30), + LineData(time: .string("2018-12-10"), value: 73.98), + LineData(time: .string("2018-12-11"), value: 72.28), + LineData(time: .string("2018-12-12"), value: 73.20), + LineData(time: .string("2018-12-13"), value: 73.00), + LineData(time: .string("2018-12-14"), value: 72.90), + LineData(time: .string("2018-12-17"), value: 73.96), + LineData(time: .string("2018-12-18"), value: 73.40), + LineData(time: .string("2018-12-19"), value: 73.00), + LineData(time: .string("2018-12-20"), value: 72.98), + LineData(time: .string("2018-12-21"), value: 72.80), + LineData(time: .string("2018-12-24"), value: 72.90), + LineData(time: .string("2018-12-25"), value: 74.20), + LineData(time: .string("2018-12-26"), value: 73.98), + LineData(time: .string("2018-12-27"), value: 74.50), + LineData(time: .string("2018-12-28"), value: 74.00), + LineData(time: .string("2019-01-03"), value: 73.50), + LineData(time: .string("2019-01-04"), value: 73.90), + LineData(time: .string("2019-01-08"), value: 73.90), + LineData(time: .string("2019-01-09"), value: 72.94), + LineData(time: .string("2019-01-10"), value: 69.86), + LineData(time: .string("2019-01-11"), value: 70.34), + LineData(time: .string("2019-01-14"), value: 68.78), + LineData(time: .string("2019-01-15"), value: 68.02), + LineData(time: .string("2019-01-16"), value: 66.60), + LineData(time: .string("2019-01-17"), value: 65.94), + LineData(time: .string("2019-01-18"), value: 68.00), + LineData(time: .string("2019-01-21"), value: 69.20), + LineData(time: .string("2019-01-22"), value: 69.76), + LineData(time: .string("2019-01-23"), value: 69.60), + LineData(time: .string("2019-01-24"), value: 69.62), + LineData(time: .string("2019-01-25"), value: 69.30), + LineData(time: .string("2019-01-28"), value: 69.20), + LineData(time: .string("2019-01-29"), value: 68.90), + LineData(time: .string("2019-01-30"), value: 66.40), + LineData(time: .string("2019-01-31"), value: 67.08), + LineData(time: .string("2019-02-01"), value: 69.78), + LineData(time: .string("2019-02-04"), value: 72.56), + LineData(time: .string("2019-02-05"), value: 72.74), + LineData(time: .string("2019-02-06"), value: 73.00), + LineData(time: .string("2019-02-07"), value: 73.38), + LineData(time: .string("2019-02-08"), value: 73.10), + LineData(time: .string("2019-02-11"), value: 73.22), + LineData(time: .string("2019-02-12"), value: 72.30), + LineData(time: .string("2019-02-13"), value: 74.86), + LineData(time: .string("2019-02-14"), value: 73.64), + LineData(time: .string("2019-02-15"), value: 73.38), + LineData(time: .string("2019-02-18"), value: 74.26), + LineData(time: .string("2019-02-19"), value: 75.00), + LineData(time: .string("2019-02-20"), value: 74.96), + LineData(time: .string("2019-02-21"), value: 75.00), + LineData(time: .string("2019-02-22"), value: 74.88), + LineData(time: .string("2019-02-25"), value: 74.96), + LineData(time: .string("2019-02-26"), value: 76.02), + LineData(time: .string("2019-02-27"), value: 77.30), + LineData(time: .string("2019-02-28"), value: 77.90), + LineData(time: .string("2019-03-01"), value: 78.24), + LineData(time: .string("2019-03-04"), value: 76.64), + LineData(time: .string("2019-03-05"), value: 78.74), + LineData(time: .string("2019-03-06"), value: 76.88), + LineData(time: .string("2019-03-07"), value: 75.32), + LineData(time: .string("2019-03-11"), value: 72.90), + LineData(time: .string("2019-03-12"), value: 74.78), + LineData(time: .string("2019-03-13"), value: 74.50), + LineData(time: .string("2019-03-14"), value: 75.34), + LineData(time: .string("2019-03-15"), value: 74.92), + LineData(time: .string("2019-03-18"), value: 75.08), + LineData(time: .string("2019-03-19"), value: 75.54), + LineData(time: .string("2019-03-20"), value: 76.78), + LineData(time: .string("2019-03-21"), value: 77.70), + LineData(time: .string("2019-03-22"), value: 77.34), + LineData(time: .string("2019-03-25"), value: 78.00), + LineData(time: .string("2019-03-26"), value: 77.98), + LineData(time: .string("2019-03-27"), value: 78.90), + LineData(time: .string("2019-03-28"), value: 78.30), + LineData(time: .string("2019-03-29"), value: 78.70), + LineData(time: .string("2019-04-01"), value: 77.22), + LineData(time: .string("2019-04-02"), value: 76.64), + LineData(time: .string("2019-04-03"), value: 76.50), + LineData(time: .string("2019-04-04"), value: 76.64), + LineData(time: .string("2019-04-05"), value: 75.46), + LineData(time: .string("2019-04-08"), value: 76.42), + LineData(time: .string("2019-04-09"), value: 77.76), + LineData(time: .string("2019-04-10"), value: 77.68), + LineData(time: .string("2019-04-11"), value: 76.60), + LineData(time: .string("2019-04-12"), value: 76.78), + LineData(time: .string("2019-04-15"), value: 76.28), + LineData(time: .string("2019-04-16"), value: 75.88), + LineData(time: .string("2019-04-17"), value: 76.38), + LineData(time: .string("2019-04-18"), value: 77.00), + LineData(time: .string("2019-04-19"), value: 77.40), + LineData(time: .string("2019-04-22"), value: 77.40), + LineData(time: .string("2019-04-23"), value: 78.20), + LineData(time: .string("2019-04-24"), value: 78.68), + LineData(time: .string("2019-04-25"), value: 78.66), + LineData(time: .string("2019-04-26"), value: 77.88), + LineData(time: .string("2019-04-29"), value: 78.02), + LineData(time: .string("2019-04-30"), value: 78.68), + LineData(time: .string("2019-05-02"), value: 78.14), + LineData(time: .string("2019-05-03"), value: 78.30), + LineData(time: .string("2019-05-06"), value: 80.06), + LineData(time: .string("2019-05-07"), value: 80.50), + LineData(time: .string("2019-05-08"), value: 80.76), + LineData(time: .string("2019-05-10"), value: 82.10), + LineData(time: .string("2019-05-13"), value: 83.72), + LineData(time: .string("2019-05-14"), value: 83.55), + LineData(time: .string("2019-05-15"), value: 84.92), + LineData(time: .string("2019-05-16"), value: 83.32), + LineData(time: .string("2019-05-17"), value: 83.04), + LineData(time: .string("2019-05-20"), value: 83.92), + LineData(time: .string("2019-05-21"), value: 84.24), + LineData(time: .string("2019-05-22"), value: 84.00), + LineData(time: .string("2019-05-23"), value: 84.26), + LineData(time: .string("2019-05-24"), value: 84.00), + LineData(time: .string("2019-05-27"), value: 83.80), + LineData(time: .string("2019-05-28"), value: 84.32), + LineData(time: .string("2019-05-29"), value: 83.88), + LineData(time: .string("2019-05-30"), value: 84.58), + LineData(time: .string("2019-05-31"), value: 81.20), + LineData(time: .string("2019-06-03"), value: 84.35), + LineData(time: .string("2019-06-04"), value: 85.66), + LineData(time: .string("2019-06-05"), value: 86.51) + ] + + override func viewDidLoad() { + super.viewDidLoad() + if #available(iOS 13.0, *) { + view.backgroundColor = .systemBackground + } else { + view.backgroundColor = .white + } + + setupUI() + setupData() + setupSubscription() + setLastBarText() + } + + private func setupUI() { + let padding: CGFloat = 16 + legendLabel.text = legend + legendLabel.font = .systemFont(ofSize: 18) + legendLabel.textColor = .darkText + legendLabel.numberOfLines = 3 + view.addSubview(legendLabel) + legendLabel.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + legendLabel.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: padding), + legendLabel.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -padding), + legendLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: padding) + ]) + } else { + NSLayoutConstraint.activate([ + legendLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: padding), + legendLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -padding), + legendLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: padding) + ]) + } + + let options = ChartOptions( + rightPriceScale: VisiblePriceScaleOptions( + scaleMargins: PriceScaleMargins(top: 0.35, bottom: 0.2), + borderVisible: false + ), + timeScale: TimeScaleOptions(borderVisible: false), + crosshair: CrosshairOptions( + vertLine: CrosshairLineOptions( + color: "rgba(32, 38, 46, 0.1)", + width: .two, + style: .solid, + visible: true, + labelVisible: false + ), + horzLine: CrosshairLineOptions(visible: false, labelVisible: false) + ), + grid: GridOptions( + verticalLines: GridLineOptions(color: "#ffffff"), + horizontalLines: GridLineOptions(color: "#eee", visible: false) + ) + ) + let chart = LightweightCharts(options: options) + view.addSubview(chart) + chart.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + ]) + } else { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } + self.chart = chart + + view.bringSubviewToFront(legendLabel) + } + + private func setupData() { + let options = AreaSeriesOptions( + topColor: "rgba(19, 68, 193, 0.4)", + bottomColor: "rgba(0, 120, 255, 0.0)", + lineColor: "rgba(19, 40, 153, 1.0)", + lineWidth: .three + ) + let series = chart.addAreaSeries(options: options) + series.setData(data: data) + self.series = series + } + + private func setupSubscription() { + chart.delegate = self + chart.subscribeCrosshairMove() + } + + private func setLastBarText() { + let bar = data.last! + let dateString: String + switch bar.time { + case let .businessDay(date): + dateString = "\(date.year) - \(date.month) - \(date.day)" + case let .string(date): + dateString = date.split(separator: "-").joined(separator: " - ") + case let .utc(timestamp: date): + dateString = "\(date)" + } + legendLabel.text = "\(legend)\n\((bar.value! * 100).rounded() / 100)\n\(dateString)" + } + +} + +// MARK: - ChartDelegate +extension ThreeLineLegendViewController: ChartDelegate { + + func didClick(onChart chart: ChartApi, parameters: MouseEventParams) { + + } + + func didCrosshairMove(onChart chart: ChartApi, parameters: MouseEventParams) { + if case let .businessDay(date) = parameters.time, + case let .barPrice(price) = parameters.price(forSeries: series) { + + let dateString = "\(date.year) - \(date.month) - \(date.day)" + self.legendLabel.text = "\(self.legend)\n\((price * 100).rounded() / 100)\n\(dateString)" + } else { + setLastBarText() + } + } + + func didVisibleTimeRangeChange(onChart chart: ChartApi, parameters: TimeRange?) { + + } + +} diff --git a/ExampleSPM/LightweightCharts/Example/TrackingTooltipViewController.swift b/ExampleSPM/LightweightCharts/Example/TrackingTooltipViewController.swift new file mode 100644 index 0000000..ff4ac03 --- /dev/null +++ b/ExampleSPM/LightweightCharts/Example/TrackingTooltipViewController.swift @@ -0,0 +1,270 @@ +import UIKit +import LightweightCharts + +class TrackingTooltipViewController: UIViewController { + + private var chart: LightweightCharts! + private var series: AreaSeries! + private let tooltipView = TooltipView(accentColor: UIColor(red: 1, green: 82/255.0, blue: 82/255.0, alpha: 1)) + private let legend = "Apple Inc." + + private var leadingConstraint: NSLayoutConstraint! + private var bottomConstraint: NSLayoutConstraint! + + override func viewDidLoad() { + super.viewDidLoad() + if #available(iOS 13.0, *) { + view.backgroundColor = .systemBackground + } else { + view.backgroundColor = .white + } + + setupUI() + setupData() + setupSubscription() + } + + private func setupUI() { + let options = ChartOptions( + layout: LayoutOptions(backgroundColor: "#ffffff", textColor: "#333"), + rightPriceScale: VisiblePriceScaleOptions( + scaleMargins: PriceScaleMargins(top: 0.2, bottom: 0.2), + borderVisible: false + ), + timeScale: TimeScaleOptions(borderVisible: false), + grid: GridOptions( + verticalLines: GridLineOptions(color: "#ffffff"), + horizontalLines: GridLineOptions(color: "#eee") + ) + ) + let chart = LightweightCharts(options: options) + view.addSubview(chart) + chart.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + ]) + } else { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } + self.chart = chart + + view.addSubview(tooltipView) + + tooltipView.translatesAutoresizingMaskIntoConstraints = false + leadingConstraint = tooltipView.leadingAnchor.constraint(equalTo: chart.leadingAnchor) + bottomConstraint = tooltipView.bottomAnchor.constraint(equalTo: chart.topAnchor) + leadingConstraint.isActive = true + bottomConstraint.isActive = true + + tooltipView.isHidden = true + + view.bringSubviewToFront(tooltipView) + } + + private func setupData() { + let options = AreaSeriesOptions( + topColor: "rgba(255, 82, 82, 0.56)", + bottomColor: "rgba(255, 82, 82, 0.04)", + lineColor: "rgba(255, 82, 82, 1)", + lineWidth: .two + ) + let series = chart.addAreaSeries(options: options) + let data = [ + LineData(time: .string("2016-07-18"), value: 98.66), + LineData(time: .string("2016-07-25"), value: 104.21), + LineData(time: .string("2016-08-01"), value: 107.48), + LineData(time: .string("2016-08-08"), value: 108.18), + LineData(time: .string("2016-08-15"), value: 109.36), + LineData(time: .string("2016-08-22"), value: 106.94), + LineData(time: .string("2016-08-29"), value: 107.73), + LineData(time: .string("2016-09-05"), value: 103.13), + LineData(time: .string("2016-09-12"), value: 114.92), + LineData(time: .string("2016-09-19"), value: 112.71), + LineData(time: .string("2016-09-26"), value: 113.05), + LineData(time: .string("2016-10-03"), value: 114.06), + LineData(time: .string("2016-10-10"), value: 117.63), + LineData(time: .string("2016-10-17"), value: 116.60), + LineData(time: .string("2016-10-24"), value: 113.72), + LineData(time: .string("2016-10-31"), value: 108.84), + LineData(time: .string("2016-11-07"), value: 108.43), + LineData(time: .string("2016-11-14"), value: 110.06), + LineData(time: .string("2016-11-21"), value: 111.79), + LineData(time: .string("2016-11-28"), value: 109.90), + LineData(time: .string("2016-12-05"), value: 113.95), + LineData(time: .string("2016-12-12"), value: 115.97), + LineData(time: .string("2016-12-19"), value: 116.52), + LineData(time: .string("2016-12-26"), value: 115.82), + LineData(time: .string("2017-01-02"), value: 117.91), + LineData(time: .string("2017-01-09"), value: 119.04), + LineData(time: .string("2017-01-16"), value: 120.00), + LineData(time: .string("2017-01-23"), value: 121.95), + LineData(time: .string("2017-01-30"), value: 129.08), + LineData(time: .string("2017-02-06"), value: 132.12), + LineData(time: .string("2017-02-13"), value: 135.72), + LineData(time: .string("2017-02-20"), value: 136.66), + LineData(time: .string("2017-02-27"), value: 139.78), + LineData(time: .string("2017-03-06"), value: 139.14), + LineData(time: .string("2017-03-13"), value: 139.99), + LineData(time: .string("2017-03-20"), value: 140.64), + LineData(time: .string("2017-03-27"), value: 143.66), + LineData(time: .string("2017-04-03"), value: 143.34), + LineData(time: .string("2017-04-10"), value: 141.05), + LineData(time: .string("2017-04-17"), value: 142.27), + LineData(time: .string("2017-04-24"), value: 143.65), + LineData(time: .string("2017-05-01"), value: 148.96), + LineData(time: .string("2017-05-08"), value: 156.10), + LineData(time: .string("2017-05-15"), value: 153.06), + LineData(time: .string("2017-05-22"), value: 153.61), + LineData(time: .string("2017-05-29"), value: 155.45), + LineData(time: .string("2017-06-05"), value: 148.98), + LineData(time: .string("2017-06-12"), value: 142.27), + LineData(time: .string("2017-06-19"), value: 146.28), + LineData(time: .string("2017-06-26"), value: 144.02), + LineData(time: .string("2017-07-03"), value: 144.18), + LineData(time: .string("2017-07-10"), value: 149.04), + LineData(time: .string("2017-07-17"), value: 150.27), + LineData(time: .string("2017-07-24"), value: 149.50), + LineData(time: .string("2017-07-31"), value: 156.39), + LineData(time: .string("2017-08-07"), value: 157.48), + LineData(time: .string("2017-08-14"), value: 157.50), + LineData(time: .string("2017-08-21"), value: 159.86), + LineData(time: .string("2017-08-28"), value: 164.05), + LineData(time: .string("2017-09-04"), value: 158.63), + LineData(time: .string("2017-09-11"), value: 159.88), + LineData(time: .string("2017-09-18"), value: 151.89), + LineData(time: .string("2017-09-25"), value: 154.12), + LineData(time: .string("2017-10-02"), value: 155.30), + LineData(time: .string("2017-10-09"), value: 156.99), + LineData(time: .string("2017-10-16"), value: 156.25), + LineData(time: .string("2017-10-23"), value: 163.05), + LineData(time: .string("2017-10-30"), value: 172.50), + LineData(time: .string("2017-11-06"), value: 174.67), + LineData(time: .string("2017-11-13"), value: 170.15), + LineData(time: .string("2017-11-20"), value: 174.97), + LineData(time: .string("2017-11-27"), value: 171.05), + LineData(time: .string("2017-12-04"), value: 169.37), + LineData(time: .string("2017-12-11"), value: 173.97), + LineData(time: .string("2017-12-18"), value: 175.01), + LineData(time: .string("2017-12-25"), value: 169.23), + LineData(time: .string("2018-01-01"), value: 175.00), + LineData(time: .string("2018-01-08"), value: 177.09), + LineData(time: .string("2018-01-15"), value: 178.46), + LineData(time: .string("2018-01-22"), value: 171.51), + LineData(time: .string("2018-01-29"), value: 160.50), + LineData(time: .string("2018-02-05"), value: 156.41), + LineData(time: .string("2018-02-12"), value: 172.43), + LineData(time: .string("2018-02-19"), value: 175.50), + LineData(time: .string("2018-02-26"), value: 176.21), + LineData(time: .string("2018-03-05"), value: 179.98), + LineData(time: .string("2018-03-12"), value: 178.02), + LineData(time: .string("2018-03-19"), value: 164.94), + LineData(time: .string("2018-03-26"), value: 167.78), + LineData(time: .string("2018-04-02"), value: 168.38), + LineData(time: .string("2018-04-09"), value: 174.73), + LineData(time: .string("2018-04-16"), value: 165.72), + LineData(time: .string("2018-04-23"), value: 162.32), + LineData(time: .string("2018-04-30"), value: 183.83), + LineData(time: .string("2018-05-07"), value: 188.59), + LineData(time: .string("2018-05-14"), value: 186.31), + LineData(time: .string("2018-05-21"), value: 188.58), + LineData(time: .string("2018-05-28"), value: 190.24), + LineData(time: .string("2018-06-04"), value: 191.70), + LineData(time: .string("2018-06-11"), value: 188.84), + LineData(time: .string("2018-06-18"), value: 184.92), + LineData(time: .string("2018-06-25"), value: 185.11), + LineData(time: .string("2018-07-02"), value: 187.97), + LineData(time: .string("2018-07-09"), value: 191.33), + LineData(time: .string("2018-07-16"), value: 191.44), + LineData(time: .string("2018-07-23"), value: 190.98), + LineData(time: .string("2018-07-30"), value: 207.99), + LineData(time: .string("2018-08-06"), value: 207.53), + LineData(time: .string("2018-08-13"), value: 217.58), + LineData(time: .string("2018-08-20"), value: 216.16), + LineData(time: .string("2018-08-27"), value: 227.63), + LineData(time: .string("2018-09-03"), value: 221.30), + LineData(time: .string("2018-09-10"), value: 223.84), + LineData(time: .string("2018-09-17"), value: 217.66), + LineData(time: .string("2018-09-24"), value: 225.74), + LineData(time: .string("2018-10-01"), value: 224.29), + LineData(time: .string("2018-10-08"), value: 222.11), + LineData(time: .string("2018-10-15"), value: 219.31), + LineData(time: .string("2018-10-22"), value: 216.30), + LineData(time: .string("2018-10-29"), value: 207.48), + LineData(time: .string("2018-11-05"), value: 204.47), + LineData(time: .string("2018-11-12"), value: 193.53), + LineData(time: .string("2018-11-19"), value: 172.29), + LineData(time: .string("2018-11-26"), value: 178.58), + LineData(time: .string("2018-12-03"), value: 168.49), + LineData(time: .string("2018-12-10"), value: 165.48), + LineData(time: .string("2018-12-17"), value: 150.73), + LineData(time: .string("2018-12-24"), value: 156.23), + LineData(time: .string("2018-12-31"), value: 148.26), + LineData(time: .string("2019-01-07"), value: 152.29), + LineData(time: .string("2019-01-14"), value: 156.82), + LineData(time: .string("2019-01-21"), value: 157.76), + LineData(time: .string("2019-01-28"), value: 166.52), + LineData(time: .string("2019-02-04"), value: 170.41), + LineData(time: .string("2019-02-11"), value: 170.42), + LineData(time: .string("2019-02-18"), value: 172.97), + LineData(time: .string("2019-02-25"), value: 174.97), + LineData(time: .string("2019-03-04"), value: 172.91), + LineData(time: .string("2019-03-11"), value: 186.12), + LineData(time: .string("2019-03-18"), value: 191.05), + LineData(time: .string("2019-03-25"), value: 189.95), + LineData(time: .string("2019-04-01"), value: 197.00), + LineData(time: .string("2019-04-08"), value: 198.87), + LineData(time: .string("2019-04-15"), value: 203.86), + LineData(time: .string("2019-04-22"), value: 204.30), + LineData(time: .string("2019-04-29"), value: 211.75), + LineData(time: .string("2019-05-06"), value: 197.18), + LineData(time: .string("2019-05-13"), value: 189.00), + LineData(time: .string("2019-05-20"), value: 178.97), + LineData(time: .string("2019-05-27"), value: 179.03) + ] + series.setData(data: data) + self.series = series + } + + private func setupSubscription() { + chart.delegate = self + chart.subscribeCrosshairMove() + } + +} + +// MARK: - ChartDelegate +extension TrackingTooltipViewController: ChartDelegate { + + func didClick(onChart chart: ChartApi, parameters: MouseEventParams) { + + } + + func didCrosshairMove(onChart chart: ChartApi, parameters: MouseEventParams) { + if case let .businessDay(date) = parameters.time, + let point = parameters.point, + case let .barPrice(price) = parameters.price(forSeries: series) { + + let dateString = "\(date.year) - \(date.month) - \(date.day)" + tooltipView.update(title: legend, price: price, date: dateString) + tooltipView.isHidden = false + leadingConstraint.constant = CGFloat(point.x) + 16 + bottomConstraint.constant = CGFloat(point.y) - 16 + } else { + self.tooltipView.isHidden = true + } + } + + func didVisibleTimeRangeChange(onChart chart: ChartApi, parameters: TimeRange?) { + + } + +} diff --git a/ExampleSPM/LightweightCharts/Example/VolumeStudyViewController.swift b/ExampleSPM/LightweightCharts/Example/VolumeStudyViewController.swift new file mode 100644 index 0000000..e765d8e --- /dev/null +++ b/ExampleSPM/LightweightCharts/Example/VolumeStudyViewController.swift @@ -0,0 +1,382 @@ +import UIKit +import LightweightCharts + +class VolumeStudyViewController: UIViewController { + + private var chart: LightweightCharts! + private var areaSeries: AreaSeries! + private var volumeSeries: HistogramSeries! + + private var leadingConstraint: NSLayoutConstraint! + + override func viewDidLoad() { + super.viewDidLoad() + if #available(iOS 13.0, *) { + view.backgroundColor = .systemBackground + } else { + view.backgroundColor = .white + } + + setupUI() + setupData() + } + + private func setupUI() { + let options = ChartOptions( + layout: LayoutOptions(backgroundColor: "#131722", textColor: "#d1d4dc"), + rightPriceScale: VisiblePriceScaleOptions( + scaleMargins: PriceScaleMargins(top: 0.3, bottom: 0.25), + borderVisible: false + ), + grid: GridOptions( + verticalLines: GridLineOptions(color: "rgba(42, 46, 57, 0)"), + horizontalLines: GridLineOptions(color: "rgba(42, 46, 57, 0.6)") + ) + ) + let chart = LightweightCharts(options: options) + view.addSubview(chart) + chart.translatesAutoresizingMaskIntoConstraints = false + if #available(iOS 11.0, *) { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + ]) + } else { + NSLayoutConstraint.activate([ + chart.leadingAnchor.constraint(equalTo: view.leadingAnchor), + chart.trailingAnchor.constraint(equalTo: view.trailingAnchor), + chart.topAnchor.constraint(equalTo: view.topAnchor), + chart.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } + self.chart = chart + } + + private func setupData() { + let areaSeriesOptions = AreaSeriesOptions( + topColor: "rgba(38,198,218, 0.56)", + bottomColor: "rgba(38,198,218, 0.04)", + lineColor: "rgba(38,198,218, 1)", + lineWidth: .two + ) + let areaSeries = chart.addAreaSeries(options: areaSeriesOptions) + let areaData = [ + LineData(time: .string("2018-10-19"), value: 54.90), + LineData(time: .string("2018-10-22"), value: 54.98), + LineData(time: .string("2018-10-23"), value: 57.21), + LineData(time: .string("2018-10-24"), value: 57.42), + LineData(time: .string("2018-10-25"), value: 56.43), + LineData(time: .string("2018-10-26"), value: 55.51), + LineData(time: .string("2018-10-29"), value: 56.48), + LineData(time: .string("2018-10-30"), value: 58.18), + LineData(time: .string("2018-10-31"), value: 57.09), + LineData(time: .string("2018-11-01"), value: 56.05), + LineData(time: .string("2018-11-02"), value: 56.63), + LineData(time: .string("2018-11-05"), value: 57.21), + LineData(time: .string("2018-11-06"), value: 57.21), + LineData(time: .string("2018-11-07"), value: 57.65), + LineData(time: .string("2018-11-08"), value: 58.27), + LineData(time: .string("2018-11-09"), value: 58.46), + LineData(time: .string("2018-11-12"), value: 58.72), + LineData(time: .string("2018-11-13"), value: 58.66), + LineData(time: .string("2018-11-14"), value: 58.94), + LineData(time: .string("2018-11-15"), value: 59.08), + LineData(time: .string("2018-11-16"), value: 60.21), + LineData(time: .string("2018-11-19"), value: 60.62), + LineData(time: .string("2018-11-20"), value: 59.46), + LineData(time: .string("2018-11-21"), value: 59.16), + LineData(time: .string("2018-11-23"), value: 58.64), + LineData(time: .string("2018-11-26"), value: 59.17), + LineData(time: .string("2018-11-27"), value: 60.65), + LineData(time: .string("2018-11-28"), value: 60.06), + LineData(time: .string("2018-11-29"), value: 59.45), + LineData(time: .string("2018-11-30"), value: 60.30), + LineData(time: .string("2018-12-03"), value: 58.16), + LineData(time: .string("2018-12-04"), value: 58.09), + LineData(time: .string("2018-12-06"), value: 58.08), + LineData(time: .string("2018-12-07"), value: 57.68), + LineData(time: .string("2018-12-10"), value: 58.27), + LineData(time: .string("2018-12-11"), value: 58.85), + LineData(time: .string("2018-12-12"), value: 57.25), + LineData(time: .string("2018-12-13"), value: 57.09), + LineData(time: .string("2018-12-14"), value: 57.08), + LineData(time: .string("2018-12-17"), value: 55.95), + LineData(time: .string("2018-12-18"), value: 55.65), + LineData(time: .string("2018-12-19"), value: 55.86), + LineData(time: .string("2018-12-20"), value: 55.07), + LineData(time: .string("2018-12-21"), value: 54.92), + LineData(time: .string("2018-12-24"), value: 53.05), + LineData(time: .string("2018-12-26"), value: 54.44), + LineData(time: .string("2018-12-27"), value: 55.15), + LineData(time: .string("2018-12-28"), value: 55.27), + LineData(time: .string("2018-12-31"), value: 56.22), + LineData(time: .string("2019-01-02"), value: 56.02), + LineData(time: .string("2019-01-03"), value: 56.22), + LineData(time: .string("2019-01-04"), value: 56.36), + LineData(time: .string("2019-01-07"), value: 56.72), + LineData(time: .string("2019-01-08"), value: 58.38), + LineData(time: .string("2019-01-09"), value: 57.05), + LineData(time: .string("2019-01-10"), value: 57.60), + LineData(time: .string("2019-01-11"), value: 58.02), + LineData(time: .string("2019-01-14"), value: 58.03), + LineData(time: .string("2019-01-15"), value: 58.10), + LineData(time: .string("2019-01-16"), value: 57.08), + LineData(time: .string("2019-01-17"), value: 56.83), + LineData(time: .string("2019-01-18"), value: 57.09), + LineData(time: .string("2019-01-22"), value: 56.99), + LineData(time: .string("2019-01-23"), value: 57.76), + LineData(time: .string("2019-01-24"), value: 57.07), + LineData(time: .string("2019-01-25"), value: 56.40), + LineData(time: .string("2019-01-28"), value: 55.07), + LineData(time: .string("2019-01-29"), value: 53.28), + LineData(time: .string("2019-01-30"), value: 54.00), + LineData(time: .string("2019-01-31"), value: 55.06), + LineData(time: .string("2019-02-01"), value: 54.55), + LineData(time: .string("2019-02-04"), value: 54.04), + LineData(time: .string("2019-02-05"), value: 54.14), + LineData(time: .string("2019-02-06"), value: 53.79), + LineData(time: .string("2019-02-07"), value: 53.57), + LineData(time: .string("2019-02-08"), value: 53.95), + LineData(time: .string("2019-02-11"), value: 54.05), + LineData(time: .string("2019-02-12"), value: 54.42), + LineData(time: .string("2019-02-13"), value: 54.48), + LineData(time: .string("2019-02-14"), value: 54.03), + LineData(time: .string("2019-02-15"), value: 55.16), + LineData(time: .string("2019-02-19"), value: 55.44), + LineData(time: .string("2019-02-20"), value: 55.76), + LineData(time: .string("2019-02-21"), value: 56.15), + LineData(time: .string("2019-02-22"), value: 56.92), + LineData(time: .string("2019-02-25"), value: 56.78), + LineData(time: .string("2019-02-26"), value: 56.64), + LineData(time: .string("2019-02-27"), value: 56.72), + LineData(time: .string("2019-02-28"), value: 56.92), + LineData(time: .string("2019-03-01"), value: 56.96), + LineData(time: .string("2019-03-04"), value: 56.24), + LineData(time: .string("2019-03-05"), value: 56.08), + LineData(time: .string("2019-03-06"), value: 55.68), + LineData(time: .string("2019-03-07"), value: 56.30), + LineData(time: .string("2019-03-08"), value: 56.53), + LineData(time: .string("2019-03-11"), value: 57.58), + LineData(time: .string("2019-03-12"), value: 57.43), + LineData(time: .string("2019-03-13"), value: 57.66), + LineData(time: .string("2019-03-14"), value: 57.95), + LineData(time: .string("2019-03-15"), value: 58.39), + LineData(time: .string("2019-03-18"), value: 58.07), + LineData(time: .string("2019-03-19"), value: 57.50), + LineData(time: .string("2019-03-20"), value: 57.67), + LineData(time: .string("2019-03-21"), value: 58.29), + LineData(time: .string("2019-03-22"), value: 59.76), + LineData(time: .string("2019-03-25"), value: 60.08), + LineData(time: .string("2019-03-26"), value: 60.63), + LineData(time: .string("2019-03-27"), value: 60.88), + LineData(time: .string("2019-03-28"), value: 59.08), + LineData(time: .string("2019-03-29"), value: 59.13), + LineData(time: .string("2019-04-01"), value: 59.09), + LineData(time: .string("2019-04-02"), value: 58.53), + LineData(time: .string("2019-04-03"), value: 58.87), + LineData(time: .string("2019-04-04"), value: 58.99), + LineData(time: .string("2019-04-05"), value: 59.09), + LineData(time: .string("2019-04-08"), value: 59.13), + LineData(time: .string("2019-04-09"), value: 58.40), + LineData(time: .string("2019-04-10"), value: 58.61), + LineData(time: .string("2019-04-11"), value: 58.56), + LineData(time: .string("2019-04-12"), value: 58.74), + LineData(time: .string("2019-04-15"), value: 58.71), + LineData(time: .string("2019-04-16"), value: 58.79), + LineData(time: .string("2019-04-17"), value: 57.78), + LineData(time: .string("2019-04-18"), value: 58.04), + LineData(time: .string("2019-04-22"), value: 58.37), + LineData(time: .string("2019-04-23"), value: 57.15), + LineData(time: .string("2019-04-24"), value: 57.08), + LineData(time: .string("2019-04-25"), value: 55.85), + LineData(time: .string("2019-04-26"), value: 56.58), + LineData(time: .string("2019-04-29"), value: 56.84), + LineData(time: .string("2019-04-30"), value: 57.19), + LineData(time: .string("2019-05-01"), value: 56.52), + LineData(time: .string("2019-05-02"), value: 56.99), + LineData(time: .string("2019-05-03"), value: 57.24), + LineData(time: .string("2019-05-06"), value: 56.91), + LineData(time: .string("2019-05-07"), value: 56.63), + LineData(time: .string("2019-05-08"), value: 56.38), + LineData(time: .string("2019-05-09"), value: 56.48), + LineData(time: .string("2019-05-10"), value: 56.91), + LineData(time: .string("2019-05-13"), value: 56.75), + LineData(time: .string("2019-05-14"), value: 56.55), + LineData(time: .string("2019-05-15"), value: 56.81), + LineData(time: .string("2019-05-16"), value: 57.38), + LineData(time: .string("2019-05-17"), value: 58.09), + LineData(time: .string("2019-05-20"), value: 59.01), + LineData(time: .string("2019-05-21"), value: 59.50), + LineData(time: .string("2019-05-22"), value: 59.25), + LineData(time: .string("2019-05-23"), value: 58.87), + LineData(time: .string("2019-05-24"), value: 59.32), + LineData(time: .string("2019-05-28"), value: 59.57) + ] + areaSeries.setData(data: areaData) + self.areaSeries = areaSeries + + let volumeSeriesOptions = HistogramSeriesOptions( + priceLineVisible: false, + priceFormat: .builtIn(BuiltInPriceFormat(type: .volume, precision: nil, minMove: nil)), + color: "#26a69a" + ) + let volumeSeries = chart.addHistogramSeries(options: volumeSeriesOptions) + let volumeData = [ + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2018-10-19"), value: 19103293.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2018-10-22"), value: 21737523.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2018-10-23"), value: 29328713.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2018-10-24"), value: 37435638.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2018-10-25"), value: 25269995.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2018-10-26"), value: 24973311.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2018-10-29"), value: 22103692.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2018-10-30"), value: 25231199.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2018-10-31"), value: 24214427.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2018-11-01"), value: 22533201.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2018-11-02"), value: 14734412.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2018-11-05"), value: 12733842.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2018-11-06"), value: 12371207.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2018-11-07"), value: 14891287.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2018-11-08"), value: 12482392.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2018-11-09"), value: 17365762.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2018-11-12"), value: 13236769.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2018-11-13"), value: 13047907.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2018-11-14"), value: 18288710.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2018-11-15"), value: 17147123.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2018-11-16"), value: 19470986.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2018-11-19"), value: 18405731.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2018-11-20"), value: 22028957.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2018-11-21"), value: 18482233.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2018-11-23"), value: 7009050.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2018-11-26"), value: 12308876.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2018-11-27"), value: 14118867.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2018-11-28"), value: 18662989.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2018-11-29"), value: 14763658.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2018-11-30"), value: 31142818.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2018-12-03"), value: 27795428.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2018-12-04"), value: 21727411.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2018-12-06"), value: 26880429.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2018-12-07"), value: 16948126.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2018-12-10"), value: 16603356.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2018-12-11"), value: 14991438.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2018-12-12"), value: 18892182.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2018-12-13"), value: 15454706.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2018-12-14"), value: 13960870.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2018-12-17"), value: 18902523.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2018-12-18"), value: 18895777.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2018-12-19"), value: 20968473.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2018-12-20"), value: 26897008.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2018-12-21"), value: 55413082.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2018-12-24"), value: 15077207.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2018-12-26"), value: 17970539.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2018-12-27"), value: 17530977.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2018-12-28"), value: 14771641.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2018-12-31"), value: 15331758.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-01-02"), value: 13969691.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-01-03"), value: 19245411.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-01-04"), value: 17035848.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-01-07"), value: 16348982.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-01-08"), value: 21425008.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-01-09"), value: 18136000.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-01-10"), value: 14259910.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-01-11"), value: 15801548.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-01-14"), value: 11342293.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-01-15"), value: 10074386.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-01-16"), value: 13411691.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-01-17"), value: 15223854.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-01-18"), value: 16802516.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-01-22"), value: 18284771.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-01-23"), value: 15109007.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-01-24"), value: 12494109.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-01-25"), value: 17806822.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-01-28"), value: 25955718.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-01-29"), value: 33789235.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-01-30"), value: 27260036.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-01-31"), value: 28585447.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-02-01"), value: 13778392.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-02-04"), value: 15818901.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-02-05"), value: 14124794.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-02-06"), value: 11391442.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-02-07"), value: 12436168.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-02-08"), value: 12011657.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-02-11"), value: 9802798.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-02-12"), value: 11227550.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-02-13"), value: 11884803.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-02-14"), value: 11190094.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-02-15"), value: 15719416.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-02-19"), value: 12272877.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-02-20"), value: 11379006.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-02-21"), value: 14680547.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-02-22"), value: 12534431.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-02-25"), value: 15051182.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-02-26"), value: 12005571.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-02-27"), value: 8962776.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-02-28"), value: 15742971.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-03-01"), value: 10942737.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-03-04"), value: 13674737.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-03-05"), value: 15749545.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-03-06"), value: 13935530.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-03-07"), value: 12644171.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-03-08"), value: 10646710.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-03-11"), value: 13627431.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-03-12"), value: 12812980.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-03-13"), value: 14168350.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-03-14"), value: 12148349.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-03-15"), value: 23715337.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-03-18"), value: 12168133.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-03-19"), value: 13462686.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-03-20"), value: 11903104.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-03-21"), value: 10920129.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-03-22"), value: 25125385.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-03-25"), value: 15463411.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-03-26"), value: 12316901.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-03-27"), value: 13290298.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-03-28"), value: 20547060.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-03-29"), value: 17283871.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-04-01"), value: 16331140.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-04-02"), value: 11408146.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-04-03"), value: 15491724.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-04-04"), value: 8776028.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-04-05"), value: 11497780.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-04-08"), value: 11680538.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-04-09"), value: 10414416.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-04-10"), value: 8782061.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-04-11"), value: 9219930.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-04-12"), value: 10847504.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-04-15"), value: 7741472.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-04-16"), value: 10239261.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-04-17"), value: 15498037.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-04-18"), value: 13189013.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-04-22"), value: 11950365.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-04-23"), value: 23488682.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-04-24"), value: 13227084.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-04-25"), value: 17425466.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-04-26"), value: 16329727.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-04-29"), value: 13984965.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-04-30"), value: 15469002.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-05-01"), value: 11627436.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-05-02"), value: 14435436.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-05-03"), value: 9388228.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-05-06"), value: 10066145.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-05-07"), value: 12963827.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-05-08"), value: 12086743.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-05-09"), value: 14835326.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-05-10"), value: 10707335.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-05-13"), value: 13759350.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-05-14"), value: 12776175.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-05-15"), value: 10806379.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-05-16"), value: 11695064.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-05-17"), value: 14436662.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-05-20"), value: 20910590.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-05-21"), value: 14016315.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-05-22"), value: 11487448.00), + HistogramData(color: "rgba(255,82,82, 0.8)", time: .string("2019-05-23"), value: 11707083.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-05-24"), value: 8755506.00), + HistogramData(color: "rgba(0, 150, 136, 0.8)", time: .string("2019-05-28"), value: 3097125.00) + ] + volumeSeries.setData(data: volumeData) + self.volumeSeries = volumeSeries + } + +} diff --git a/ExampleSPM/LightweightCharts/Images.xcassets/AppIcon.appiconset/Contents.json b/ExampleSPM/LightweightCharts/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..7006c9e --- /dev/null +++ b/ExampleSPM/LightweightCharts/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,53 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/ExampleSPM/LightweightCharts/Info.plist b/ExampleSPM/LightweightCharts/Info.plist new file mode 100644 index 0000000..9d1bc55 --- /dev/null +++ b/ExampleSPM/LightweightCharts/Info.plist @@ -0,0 +1,37 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(MARKETING_VERSION) + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + + + diff --git a/ExampleSPM/LightweightCharts/Views/TooltipView.swift b/ExampleSPM/LightweightCharts/Views/TooltipView.swift new file mode 100644 index 0000000..2f25cbc --- /dev/null +++ b/ExampleSPM/LightweightCharts/Views/TooltipView.swift @@ -0,0 +1,70 @@ +import UIKit + +class TooltipView: UIView { + + private let titleLabel = UILabel() + private let priceLabel = UILabel() + private let dateLabel = UILabel() + + private let accentColor: UIColor + + init(accentColor: UIColor) { + self.accentColor = accentColor + super.init(frame: .zero) + + layer.borderWidth = 2 + backgroundColor = .white + isUserInteractionEnabled = false + setupSubviews() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func update(title: String, price: Double, date: String) { + titleLabel.text = title + priceLabel.text = "\((price * 100).rounded() / 100)" + dateLabel.text = date + } + + private func setupSubviews() { + self.layer.borderColor = accentColor.cgColor + + titleLabel.textColor = accentColor + priceLabel.textColor = .darkText + dateLabel.textColor = .darkText + + priceLabel.font = .systemFont(ofSize: 24) + + titleLabel.textAlignment = .natural + priceLabel.textAlignment = .natural + dateLabel.textAlignment = .natural + + addSubview(titleLabel) + addSubview(priceLabel) + addSubview(dateLabel) + + titleLabel.translatesAutoresizingMaskIntoConstraints = false + priceLabel.translatesAutoresizingMaskIntoConstraints = false + dateLabel.translatesAutoresizingMaskIntoConstraints = false + + let padding: CGFloat = 8 + NSLayoutConstraint.activate([ + titleLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: padding), + titleLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -padding), + titleLabel.topAnchor.constraint(equalTo: topAnchor, constant: padding), + + priceLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: padding), + priceLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -padding), + priceLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: padding), + + dateLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: padding), + dateLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -padding), + dateLabel.topAnchor.constraint(equalTo: priceLabel.bottomAnchor, constant: padding), + dateLabel.bottomAnchor.constraint(lessThanOrEqualTo: bottomAnchor, constant: -padding), + ]) + + } + +} diff --git a/ExampleSPM/Tests/Info.plist b/ExampleSPM/Tests/Info.plist new file mode 100644 index 0000000..ba72822 --- /dev/null +++ b/ExampleSPM/Tests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/ExampleSPM/Tests/Tests.swift b/ExampleSPM/Tests/Tests.swift new file mode 100644 index 0000000..05c0d6c --- /dev/null +++ b/ExampleSPM/Tests/Tests.swift @@ -0,0 +1,16 @@ +import XCTest +import LightweightCharts + +class Tests: XCTestCase { + + override func setUp() { + super.setUp() + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. + super.tearDown() + } + +} diff --git a/LightwehgitCharts/LightwehgitCharts.xcodeproj/project.pbxproj b/LightwehgitCharts/LightwehgitCharts.xcodeproj/project.pbxproj new file mode 100644 index 0000000..753d0db --- /dev/null +++ b/LightwehgitCharts/LightwehgitCharts.xcodeproj/project.pbxproj @@ -0,0 +1,469 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 55; + objects = { + +/* Begin PBXBuildFile section */ + FA621D402720770A000F40B0 /* LightwehgitCharts.docc in Sources */ = {isa = PBXBuildFile; fileRef = FA621D3F2720770A000F40B0 /* LightwehgitCharts.docc */; }; + FA621D462720770A000F40B0 /* LightwehgitCharts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA621D3B2720770A000F40B0 /* LightwehgitCharts.framework */; }; + FA621D4B2720770A000F40B0 /* LightwehgitChartsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA621D4A2720770A000F40B0 /* LightwehgitChartsTests.swift */; }; + FA621D4C2720770A000F40B0 /* LightwehgitCharts.h in Headers */ = {isa = PBXBuildFile; fileRef = FA621D3E2720770A000F40B0 /* LightwehgitCharts.h */; settings = {ATTRIBUTES = (Public, ); }; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + FA621D472720770A000F40B0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = FA621D322720770A000F40B0 /* Project object */; + proxyType = 1; + remoteGlobalIDString = FA621D3A2720770A000F40B0; + remoteInfo = LightwehgitCharts; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + FA621D3B2720770A000F40B0 /* LightwehgitCharts.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LightwehgitCharts.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + FA621D3E2720770A000F40B0 /* LightwehgitCharts.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LightwehgitCharts.h; sourceTree = ""; }; + FA621D3F2720770A000F40B0 /* LightwehgitCharts.docc */ = {isa = PBXFileReference; lastKnownFileType = folder.documentationcatalog; path = LightwehgitCharts.docc; sourceTree = ""; }; + FA621D452720770A000F40B0 /* LightwehgitChartsTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LightwehgitChartsTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + FA621D4A2720770A000F40B0 /* LightwehgitChartsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LightwehgitChartsTests.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + FA621D382720770A000F40B0 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FA621D422720770A000F40B0 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + FA621D462720770A000F40B0 /* LightwehgitCharts.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + FA621D312720770A000F40B0 = { + isa = PBXGroup; + children = ( + FA621D3D2720770A000F40B0 /* LightwehgitCharts */, + FA621D492720770A000F40B0 /* LightwehgitChartsTests */, + FA621D3C2720770A000F40B0 /* Products */, + ); + sourceTree = ""; + }; + FA621D3C2720770A000F40B0 /* Products */ = { + isa = PBXGroup; + children = ( + FA621D3B2720770A000F40B0 /* LightwehgitCharts.framework */, + FA621D452720770A000F40B0 /* LightwehgitChartsTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + FA621D3D2720770A000F40B0 /* LightwehgitCharts */ = { + isa = PBXGroup; + children = ( + FA621D3E2720770A000F40B0 /* LightwehgitCharts.h */, + FA621D3F2720770A000F40B0 /* LightwehgitCharts.docc */, + ); + path = LightwehgitCharts; + sourceTree = ""; + }; + FA621D492720770A000F40B0 /* LightwehgitChartsTests */ = { + isa = PBXGroup; + children = ( + FA621D4A2720770A000F40B0 /* LightwehgitChartsTests.swift */, + ); + path = LightwehgitChartsTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + FA621D362720770A000F40B0 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + FA621D4C2720770A000F40B0 /* LightwehgitCharts.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + FA621D3A2720770A000F40B0 /* LightwehgitCharts */ = { + isa = PBXNativeTarget; + buildConfigurationList = FA621D4F2720770A000F40B0 /* Build configuration list for PBXNativeTarget "LightwehgitCharts" */; + buildPhases = ( + FA621D362720770A000F40B0 /* Headers */, + FA621D372720770A000F40B0 /* Sources */, + FA621D382720770A000F40B0 /* Frameworks */, + FA621D392720770A000F40B0 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = LightwehgitCharts; + productName = LightwehgitCharts; + productReference = FA621D3B2720770A000F40B0 /* LightwehgitCharts.framework */; + productType = "com.apple.product-type.framework"; + }; + FA621D442720770A000F40B0 /* LightwehgitChartsTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = FA621D522720770A000F40B0 /* Build configuration list for PBXNativeTarget "LightwehgitChartsTests" */; + buildPhases = ( + FA621D412720770A000F40B0 /* Sources */, + FA621D422720770A000F40B0 /* Frameworks */, + FA621D432720770A000F40B0 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + FA621D482720770A000F40B0 /* PBXTargetDependency */, + ); + name = LightwehgitChartsTests; + productName = LightwehgitChartsTests; + productReference = FA621D452720770A000F40B0 /* LightwehgitChartsTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + FA621D322720770A000F40B0 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1300; + LastUpgradeCheck = 1300; + TargetAttributes = { + FA621D3A2720770A000F40B0 = { + CreatedOnToolsVersion = 13.0; + }; + FA621D442720770A000F40B0 = { + CreatedOnToolsVersion = 13.0; + }; + }; + }; + buildConfigurationList = FA621D352720770A000F40B0 /* Build configuration list for PBXProject "LightwehgitCharts" */; + compatibilityVersion = "Xcode 13.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = FA621D312720770A000F40B0; + productRefGroup = FA621D3C2720770A000F40B0 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + FA621D3A2720770A000F40B0 /* LightwehgitCharts */, + FA621D442720770A000F40B0 /* LightwehgitChartsTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + FA621D392720770A000F40B0 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FA621D432720770A000F40B0 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + FA621D372720770A000F40B0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FA621D402720770A000F40B0 /* LightwehgitCharts.docc in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FA621D412720770A000F40B0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FA621D4B2720770A000F40B0 /* LightwehgitChartsTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + FA621D482720770A000F40B0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FA621D3A2720770A000F40B0 /* LightwehgitCharts */; + targetProxy = FA621D472720770A000F40B0 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + FA621D4D2720770A000F40B0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + FA621D4E2720770A000F40B0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + FA621D502720770A000F40B0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.tradingview.LightwehgitCharts; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + FA621D512720770A000F40B0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.tradingview.LightwehgitCharts; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + FA621D532720770A000F40B0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.tradingview.LightwehgitChartsTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + FA621D542720770A000F40B0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.tradingview.LightwehgitChartsTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + FA621D352720770A000F40B0 /* Build configuration list for PBXProject "LightwehgitCharts" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FA621D4D2720770A000F40B0 /* Debug */, + FA621D4E2720770A000F40B0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FA621D4F2720770A000F40B0 /* Build configuration list for PBXNativeTarget "LightwehgitCharts" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FA621D502720770A000F40B0 /* Debug */, + FA621D512720770A000F40B0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FA621D522720770A000F40B0 /* Build configuration list for PBXNativeTarget "LightwehgitChartsTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FA621D532720770A000F40B0 /* Debug */, + FA621D542720770A000F40B0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = FA621D322720770A000F40B0 /* Project object */; +} diff --git a/LightwehgitCharts/LightwehgitCharts.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/LightwehgitCharts/LightwehgitCharts.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/LightwehgitCharts/LightwehgitCharts.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/LightwehgitCharts/LightwehgitCharts.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/LightwehgitCharts/LightwehgitCharts.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/LightwehgitCharts/LightwehgitCharts.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/LightwehgitCharts/LightwehgitCharts/LightwehgitCharts.docc/LightwehgitCharts.md b/LightwehgitCharts/LightwehgitCharts/LightwehgitCharts.docc/LightwehgitCharts.md new file mode 100755 index 0000000..c8144cd --- /dev/null +++ b/LightwehgitCharts/LightwehgitCharts/LightwehgitCharts.docc/LightwehgitCharts.md @@ -0,0 +1,13 @@ +# ``LightwehgitCharts`` + +Summary + +## Overview + +Text + +## Topics + +### Group + +- ``Symbol`` \ No newline at end of file diff --git a/LightwehgitCharts/LightwehgitCharts/LightwehgitCharts.h b/LightwehgitCharts/LightwehgitCharts/LightwehgitCharts.h new file mode 100644 index 0000000..f2dee62 --- /dev/null +++ b/LightwehgitCharts/LightwehgitCharts/LightwehgitCharts.h @@ -0,0 +1,18 @@ +// +// LightwehgitCharts.h +// LightwehgitCharts +// +// Created by Alex Nevyantsev on 10/20/21. +// + +#import + +//! Project version number for LightwehgitCharts. +FOUNDATION_EXPORT double LightwehgitChartsVersionNumber; + +//! Project version string for LightwehgitCharts. +FOUNDATION_EXPORT const unsigned char LightwehgitChartsVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + + diff --git a/LightwehgitCharts/LightwehgitChartsTests/LightwehgitChartsTests.swift b/LightwehgitCharts/LightwehgitChartsTests/LightwehgitChartsTests.swift new file mode 100644 index 0000000..f4ee5da --- /dev/null +++ b/LightwehgitCharts/LightwehgitChartsTests/LightwehgitChartsTests.swift @@ -0,0 +1,33 @@ +// +// LightwehgitChartsTests.swift +// LightwehgitChartsTests +// +// Created by Alex Nevyantsev on 10/20/21. +// + +import XCTest +@testable import LightwehgitCharts + +class LightwehgitChartsTests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() throws { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + } + + func testPerformanceExample() throws { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + } + } + +} diff --git a/LightweightCharts/.gitignore b/LightweightCharts/.gitignore new file mode 100644 index 0000000..bb460e7 --- /dev/null +++ b/LightweightCharts/.gitignore @@ -0,0 +1,7 @@ +.DS_Store +/.build +/Packages +/*.xcodeproj +xcuserdata/ +DerivedData/ +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata diff --git a/LightweightCharts/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/LightweightCharts/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/LightweightCharts/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/LightweightCharts/Assets/.gitkeep b/LightweightCharts/Assets/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/LightweightCharts/Assets/content-setup.js b/LightweightCharts/Assets/content-setup.js deleted file mode 100644 index 746d196..0000000 --- a/LightweightCharts/Assets/content-setup.js +++ /dev/null @@ -1,5 +0,0 @@ -var meta = document.createElement('meta'); -meta.setAttribute('name', 'viewport'); -meta.setAttribute('content', 'width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, shrink-to-fit=no'); -document.getElementsByTagName('head')[0].appendChild(meta); -document.body.style.margin = 0; diff --git a/LightweightCharts/Assets/wrapper_functions.js b/LightweightCharts/Assets/wrapper_functions.js deleted file mode 100644 index dbc9108..0000000 --- a/LightweightCharts/Assets/wrapper_functions.js +++ /dev/null @@ -1,56 +0,0 @@ -function promptFunction(objectName) { - return function(params) { - try { - var payload = {object: objectName, params: params}; - var result = prompt(JSON.stringify(payload)); - return result; - } catch(err) { - console.log('Error with function ' + object + '.') - } - } -} - -function promptTickMarkFormatterFunction(objectName) { - return function(time, tickMarkType, locale) { - try { - var payload = {object: objectName, params: {time: time, tickMarkType: tickMarkType, locale: locale}}; - var result = prompt(JSON.stringify(payload)); - return result; - } catch(err) { - console.log('Error with function ' + object + '.') - } - } -} - -function promptAutoscaleInfoProviderFunction(objectName) { - return function(baseImplementation) { - try { - var payload = {object: objectName, params: baseImplementation()}; - var result = prompt(JSON.stringify(payload)); - return JSON.parse(result); - } catch(err) { - console.log('Error with function ' + object + '.') - } - } -} - -function postMessageFunction(name) { - return function(param) { - window.webkit.messageHandlers[name].postMessage(JSON.stringify(param)); - } -} - -function subscriberCrosshairMoveAndClickFunction(name) { - return function(param) { - var parameters = param; - var dict = {}; - seriesArray.forEach(function(stored) { - var price = param.seriesPrices.get(stored.series); - if (price != null) { - dict[stored.name] = price; - } - }); - parameters.seriesPrices = dict; - window.webkit.messageHandlers[name].postMessage(JSON.stringify(parameters)); - } -} diff --git a/LightweightCharts/Classes/.gitkeep b/LightweightCharts/Classes/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/LightweightCharts/Classes/Extensions/Encodable+JSONString.swift b/LightweightCharts/Classes/Extensions/Encodable+JSONString.swift deleted file mode 100644 index f288d8c..0000000 --- a/LightweightCharts/Classes/Extensions/Encodable+JSONString.swift +++ /dev/null @@ -1,15 +0,0 @@ -import Foundation - -extension Encodable { - - /// JSON string from object encoded with JSONEncoder. - var jsonString: String { - guard let jsonData = try? JSONEncoder().encode(self), - let jsonString = String(data: jsonData, encoding: .utf8) - else { - return "" - } - return jsonString - } - -} diff --git a/LightweightCharts/Classes/Extensions/Int+ColorComponent.swift b/LightweightCharts/Classes/Extensions/Int+ColorComponent.swift deleted file mode 100644 index fea895e..0000000 --- a/LightweightCharts/Classes/Extensions/Int+ColorComponent.swift +++ /dev/null @@ -1,10 +0,0 @@ -import Foundation -import UIKit - -extension Int { - - init(colorComponent: CGFloat) { - self = Int(round(colorComponent * 255)) - } - -} diff --git a/LightweightCharts/Classes/Extensions/NSRegularExpression+Color.swift b/LightweightCharts/Classes/Extensions/NSRegularExpression+Color.swift deleted file mode 100644 index 6979f1e..0000000 --- a/LightweightCharts/Classes/Extensions/NSRegularExpression+Color.swift +++ /dev/null @@ -1,30 +0,0 @@ -import Foundation - -extension NSRegularExpression { - - /** - * Regular expression for __rgb(255, 255, 255)__ format strings - * - group 0 - whole line - * - group 1 - red - * - group 2 - green - * - group 3 - blue - */ - static var rgb: NSRegularExpression? { - let pattern = #"rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)"# - return try? NSRegularExpression(pattern: pattern, options: .caseInsensitive) - } - - /** - * Regular expression for __rgba(255, 255, 255, 1.0)__ format strings - * - group 0 - whole line - * - group 1 - red - * - group 2 - green - * - group 3 - blue - * - group 4 - alpha - */ - static var rgba: NSRegularExpression? { - let pattern = #"rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(0|1|1\.0|0\.\d+)\s*\)$"# - return try? NSRegularExpression(pattern: pattern, options: .caseInsensitive) - } - -} diff --git a/LightweightCharts/Classes/Extensions/String+UniqueString.swift b/LightweightCharts/Classes/Extensions/String+UniqueString.swift deleted file mode 100644 index ac2f71c..0000000 --- a/LightweightCharts/Classes/Extensions/String+UniqueString.swift +++ /dev/null @@ -1,9 +0,0 @@ -import Foundation - -extension String { - - static var uniqueString: String { - UUID().uuidString.replacingOccurrences(of: "-", with: "") - } - -} diff --git a/LightweightCharts/Classes/Extensions/UIColor+ColorComponents.swift b/LightweightCharts/Classes/Extensions/UIColor+ColorComponents.swift deleted file mode 100644 index ce6e75c..0000000 --- a/LightweightCharts/Classes/Extensions/UIColor+ColorComponents.swift +++ /dev/null @@ -1,11 +0,0 @@ -import Foundation - -extension UIColor { - - var components: ColorComponents { - var components = ColorComponents() - getRed(&components.red, green: &components.green, blue: &components.blue, alpha: &components.alpha) - return components - } - -} diff --git a/LightweightCharts/Classes/Implementations/API/Chart.swift b/LightweightCharts/Classes/Implementations/API/Chart.swift deleted file mode 100644 index 036fc41..0000000 --- a/LightweightCharts/Classes/Implementations/API/Chart.swift +++ /dev/null @@ -1,223 +0,0 @@ -import Foundation -import WebKit - -public protocol ChartDelegate: AnyObject { - - func didClick(onChart chart: ChartApi, parameters: MouseEventParams) - func didCrosshairMove(onChart chart: ChartApi, parameters: MouseEventParams) - -} - -// MARK: - -class Chart: JavaScriptObject { - - typealias Context = JavaScriptEvaluator & JavaScriptMessageProducer - - let jsName = "chart" + .uniqueString - - weak var delegate: ChartDelegate? - - private unowned var context: Context - private let messageHandler: MessageHandler - private weak var closureStore: ClosuresStore? - - init(context: Context, closureStore: ClosuresStore?) { - self.context = context - self.closureStore = closureStore - messageHandler = MessageHandler() - messageHandler.delegate = self - } - - private func addSeries(options: T.Options) -> T { - let series = T(context: context, closureStore: closureStore) - let optionsScript = options.optionsScript(for: closureStore) - let script = """ - \(optionsScript.options) - var \(series.jsName) = \(jsName).add\(T.name)(\(optionsScript.variableName)); - seriesArray.push({name: "\(series.jsName)", series: \(series.jsName)}); - """ - context.evaluateScript(script, completion: nil) - return series - } - - private func subsriberScript(forName name: String, subscription: Subscription) -> String { - switch subscription { - case .crosshairMove, .click: - return "var \(name) = subscriberCrosshairMoveAndClickFunction('\(name)');" - default: - return "var \(name) = postMessageFunction('\(name)');" - } - } - - private func subscriberName(for subsription: Subscription) -> String { - return "\(subsription.rawValue)_\(jsName)" - } - - private func subscribe(subscription: Subscription) { - let name = subscriberName(for: subscription) - let subscriberScript = subsriberScript(forName: name, subscription: subscription) - let script = subscriberScript + "\n\(jsName).subscribe\(subscription.jsRepresentation)(\(name));" - context.addMessageHandler(messageHandler, name: name) - context.evaluateScript(script, completion: nil) - } - - private func unsubscribe(subsription: Subscription) { - let name = subscriberName(for: subsription) - let script = "\(jsName).unsubscribe\(subsription.jsRepresentation)(\(name));" - context.evaluateScript(script, completion: nil) - } - - private func unsubscribeAll() { - unsubscribeClick() - unsubscribeCrosshairMove() - } - -} - -// MARK: - ChartApi -extension Chart: ChartApi { - - func remove() { - unsubscribeAll() - let script = "\(jsName).remove();" - context.evaluateScript(script, completion: nil) - } - - func resize(width: Double, height: Double, forceRepaint: Bool?) { - var parameters = "\(width), \(height)" - if let forceRepaint = forceRepaint { - parameters += ", \(forceRepaint)" - } - let script = "\(jsName).resize(\(parameters));" - context.evaluateScript(script, completion: nil) - } - - // MARK: Series methods - - func addAreaSeries(options: AreaSeries.Options?) -> AreaSeries { - addSeries(options: options ?? AreaSeries.Options()) - } - - func addBarSeries(options: BarSeries.Options?) -> BarSeries { - addSeries(options: options ?? BarSeries.Options()) - } - - func addCandlestickSeries(options: CandlestickSeries.Options?) -> CandlestickSeries { - addSeries(options: options ?? CandlestickSeries.Options()) - } - - func addHistogramSeries(options: HistogramSeries.Options?) -> HistogramSeries { - addSeries(options: options ?? HistogramSeries.Options()) - } - - func addLineSeries(options: LineSeries.Options?) -> LineSeries { - addSeries(options: options ?? LineSeries.Options()) - } - - func removeSeries(seriesApi: T) { - let script = "\(jsName).removeSeries(\(seriesApi.jsName));" - context.evaluateScript(script, completion: nil) - } - - // MARK: Subscriptions - - func subscribeClick() { - subscribe(subscription: .click) - } - - func unsubscribeClick() { - unsubscribe(subsription: .click) - } - - func subscribeCrosshairMove() { - subscribe(subscription: .crosshairMove) - } - - func unsubscribeCrosshairMove() { - unsubscribe(subsription: .crosshairMove) - } - - // MARK: Other APIs and options methods - - func priceScale(priceScaleId: String?) -> PriceScaleApi { - let priceScale = PriceScale(context: context) - let priceScaleId = priceScaleId ?? "" - let script = "var \(priceScale.jsName) = \(jsName).priceScale(\(priceScaleId));" - context.evaluateScript(script) { _, _ in - } - return priceScale - } - - func timeScale() -> TimeScaleApi { - let timeScale = TimeScale(context: context, closureStore: closureStore) - let script = "var \(timeScale.jsName) = \(jsName).timeScale();" - context.evaluateScript(script) { _, _ in - } - return timeScale - } - - func applyOptions(options: ChartOptions) { - let optionsScript = options.optionsScript(for: closureStore) - let script = """ - \(optionsScript.options) - \(jsName).applyOptions(\(optionsScript.variableName)); - """ - context.evaluateScript(script, completion: nil) - } - - func options(completion: @escaping (ChartOptions?) -> Void) { - let script = "\(jsName).options();" - context.decodedResult(forScript: script, completion: completion) - } - - func takeScreenshot(completion: @escaping (UIImage?) -> Void) { - let imageFormat = "image/jpeg" - let script = "\(jsName).takeScreenshot().toDataURL('\(imageFormat)', 1.0);" - context.evaluateScript(script) { (result, error) in - DispatchQueue.global().async { - var image: UIImage? - if error == nil, - let dataString = result as? String, - !dataString.isEmpty { - // format: - // data:[][;base64], - // example - // (data:image/jpeg;base64,/9j/4AAQSkZJRgA - let countToRemove = "data:\(imageFormat);base64,".count - let index = dataString.index(dataString.startIndex, offsetBy: countToRemove) - let base64String = String(dataString[index...]) - if let data = Data(base64Encoded: base64String) { - if let screenshot = UIImage(data: data) { - image = screenshot - } - } - } - completion(image) - } - } - } - -} - -// MARK: - MessageHandlerDelegate -extension Chart: MessageHandlerDelegate { - - func messageHandler(_ messageHandler: MessageHandler, - didReceiveClickWithParameters parameters: MouseEventParams) { - delegate?.didClick(onChart: self, parameters: parameters) - } - - func messageHandler(_ messageHandler: MessageHandler, - didReceiveCrosshairMoveWithParameters parameters: MouseEventParams) { - delegate?.didCrosshairMove(onChart: self, parameters: parameters) - } - - func messageHandler(_ messageHandler: MessageHandler, - didReceiveVisibleTimeRangeChangeWithParameters parameters: TimeRange?) { - } - - func messageHandler(_ messageHandler: MessageHandler, - didReceiveVisibleLogicalRangeChangeWithParameters parameters: LogicalRange?) { - } - -} diff --git a/LightweightCharts/Classes/Implementations/API/LightweightCharts.swift b/LightweightCharts/Classes/Implementations/API/LightweightCharts.swift deleted file mode 100644 index c213c1a..0000000 --- a/LightweightCharts/Classes/Implementations/API/LightweightCharts.swift +++ /dev/null @@ -1,209 +0,0 @@ -import Foundation -import WebKit - -public protocol LightweightChartsDelegate: AnyObject { - - func lightweightChartsDidLoad(_ lightweightCharts: LightweightCharts) - func lightweightCharts(_ lightweightCharts: LightweightCharts, didFailLoadWithError error: Error) - -} - -/// Lightweight Charting Library -public class LightweightCharts: UIView { - - /** - * Loding delegate for chart. Tells the delegate when the chart has loaded or when the load failed. Weak reference. - */ - public weak var loadDelegate: LightweightChartsDelegate? - public weak var errorDelegate: JavaScriptErrorDelegate? { - get { webView.errorDelegate } - set { webView.errorDelegate = newValue } - } - - private let webView: WebView = WebView() - private let promptHandler: PromptHandler = PromptHandler() - private var chart: ChartApi! - - public required init( - frame: CGRect = .zero, - options: ChartOptions = ChartOptions(), - loadDelegate: LightweightChartsDelegate? = nil - ) { - super.init(frame: frame) - - self.loadDelegate = loadDelegate - setupChart(options: options) - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - - setupChart(options: ChartOptions()) - } - - /// This function is the main entry point of the Lightweight Charting Library - /// - Parameter options: This function is the main entry point of the Lightweight Charting Library - /// - Returns: an interface to the created chart - private func createChart(options: ChartOptions?) -> ChartApi { - let chart = Chart(context: webView, closureStore: promptHandler) - let options = options ?? ChartOptions() - let optionsScript = options.optionsScript(for: promptHandler) - let script = """ - \(optionsScript.options) - var \(chart.jsName) = LightweightCharts.createChart(document.body, \(optionsScript.variableName)); - var seriesArray = []; - """ - webView.evaluateScript(script) { [weak self] (_, error) in - guard let self = self else { return } - if let error = error { - self.loadDelegate?.lightweightCharts(self, didFailLoadWithError: error) - } else { - self.loadDelegate?.lightweightChartsDidLoad(self) - } - } - self.chart = chart - return chart - } - - public override func layoutSubviews() { - super.layoutSubviews() - - webView.frame = bounds - let width = bounds.width - let height = bounds.height - chart.resize(width: width, height: height, forceRepaint: nil) - } - - private func setupChart(options: ChartOptions) { - setupWebView() - loadLibrary() - loadWrapperFunctions() - chart = createChart(options: options) - } - - private func setupWebView() { - webView.uiDelegate = promptHandler - - let scrollView = webView.scrollView - if #available(iOS 11, *) { - scrollView.contentInsetAdjustmentBehavior = .never - } - scrollView.isScrollEnabled = false - - addSubview(webView) - - evaluateScriptFromFile(withFileName: "content-setup") - } - - private func loadLibrary() { - evaluateScriptFromFile(withFileName: "lightweight-charts") - } - - private func loadWrapperFunctions() { - evaluateScriptFromFile(withFileName: "wrapper_functions") - } - - private func loadScript(withName fileName: String) throws -> String { - let bundle = Bundle(for: LightweightCharts.self) - let pathForJSRuntime = bundle.path(forResource: fileName, ofType: "js") - guard let path = pathForJSRuntime else { return "" } - return try String(contentsOfFile: path, encoding: .utf8) - } - - private func evaluateScriptFromFile(withFileName fileName: String) { - do { - let script = try loadScript(withName: fileName) - webView.evaluateJavaScript(script) { [weak self] (_, error) in - guard let self = self else { return } - if let error = error { - self.loadDelegate?.lightweightCharts(self, didFailLoadWithError: error) - } - } - } catch { - loadDelegate?.lightweightCharts(self, didFailLoadWithError: error) - } - } - -} - -// MARK: - ChartApi -extension LightweightCharts: ChartApi { - - public var delegate: ChartDelegate? { - get { - chart.delegate - } - set { - chart.delegate = newValue - } - } - - public func remove() { - chart.remove() - } - - public func resize(width: Double, height: Double, forceRepaint: Bool?) { - chart.resize(width: width, height: height, forceRepaint: forceRepaint) - } - - public func addAreaSeries(options: AreaSeries.Options?) -> AreaSeries { - chart.addAreaSeries(options: options) - } - - public func addBarSeries(options: BarSeries.Options?) -> BarSeries { - chart.addBarSeries(options: options) - } - - public func addCandlestickSeries(options: CandlestickSeries.Options?) -> CandlestickSeries { - chart.addCandlestickSeries(options: options) - } - - public func addHistogramSeries(options: HistogramSeries.Options?) -> HistogramSeries { - chart.addHistogramSeries(options: options) - } - - public func addLineSeries(options: LineSeries.Options?) -> LineSeries { - chart.addLineSeries(options: options) - } - - public func removeSeries(seriesApi: T) { - chart.removeSeries(seriesApi: seriesApi) - } - - public func subscribeClick() { - chart.subscribeClick() - } - - public func unsubscribeClick() { - chart.unsubscribeClick() - } - - public func subscribeCrosshairMove() { - chart.subscribeCrosshairMove() - } - - public func unsubscribeCrosshairMove() { - chart.unsubscribeCrosshairMove() - } - - public func priceScale(priceScaleId: String?) -> PriceScaleApi { - chart.priceScale(priceScaleId: priceScaleId) - } - - public func timeScale() -> TimeScaleApi { - chart.timeScale() - } - - public func applyOptions(options: ChartOptions) { - chart.applyOptions(options: options) - } - - public func options(completion: @escaping (ChartOptions?) -> Void) { - chart.options(completion: completion) - } - - public func takeScreenshot(completion: @escaping (UIImage?) -> Void) { - chart.takeScreenshot(completion: completion) - } - -} diff --git a/LightweightCharts/Classes/Implementations/API/PriceFormatter.swift b/LightweightCharts/Classes/Implementations/API/PriceFormatter.swift deleted file mode 100644 index 030d4c5..0000000 --- a/LightweightCharts/Classes/Implementations/API/PriceFormatter.swift +++ /dev/null @@ -1,25 +0,0 @@ -import Foundation - -class PriceFormatter: JavaScriptObject { - - let jsName = "priceFormatter" + .uniqueString - - private weak var context: JavaScriptEvaluator? - - init(context: JavaScriptEvaluator) { - self.context = context - } - -} - -// MARK: - PriceFormatterApi -extension PriceFormatter: PriceFormatterApi { - - func format(price: BarPrice, completion: @escaping (String?) -> Void) { - let script = "\(jsName).format(\(price));" - context?.evaluateScript(script) { (result, _) in - completion(result as? String) - } - } - -} diff --git a/LightweightCharts/Classes/Implementations/API/PriceLine.swift b/LightweightCharts/Classes/Implementations/API/PriceLine.swift deleted file mode 100644 index 947c036..0000000 --- a/LightweightCharts/Classes/Implementations/API/PriceLine.swift +++ /dev/null @@ -1,27 +0,0 @@ -import Foundation - -public class PriceLine: JavaScriptObject { - - let jsName = "priceLine" + .uniqueString - weak var context: JavaScriptEvaluator? - - init(context: JavaScriptEvaluator) { - self.context = context - } - -} - -// MARK: - PriceLineApi -extension PriceLine: PriceLineApi { - - public func applyOptions(options: PriceLineOptions) { - let script = "\(jsName).applyOptions(\(options.jsonString));" - context?.evaluateScript(script, completion: nil) - } - - public func options(completion: @escaping (PriceLineOptions?) -> Void) { - let script = "\(jsName).options();" - context?.decodedResult(forScript: script, completion: completion) - } - -} diff --git a/LightweightCharts/Classes/Implementations/API/PriceScale.swift b/LightweightCharts/Classes/Implementations/API/PriceScale.swift deleted file mode 100644 index e3a5da7..0000000 --- a/LightweightCharts/Classes/Implementations/API/PriceScale.swift +++ /dev/null @@ -1,35 +0,0 @@ -import Foundation - -class PriceScale: JavaScriptObject { - - let jsName = "priceScale" + .uniqueString - - private weak var context: JavaScriptEvaluator? - - init(context: JavaScriptEvaluator) { - self.context = context - } - -} - -// MARK: - PriceScaleApi -extension PriceScale: PriceScaleApi { - - func applyOptions(options: PriceScaleOptions) { - let script = "\(jsName).applyOptions(\(options.jsonString));" - context?.evaluateScript(script, completion: nil) - } - - func options(completion: @escaping (PriceScaleOptions?) -> Void) { - let script = "\(jsName).options();" - context?.decodedResult(forScript: script, completion: completion) - } - - func width(completion: @escaping (Double?) -> Void) { - let script = "\(jsName).width();" - context?.evaluateScript(script) { result, _ in - completion(result as? Double) - } - } - -} diff --git a/LightweightCharts/Classes/Implementations/API/Series/AreaSeries.swift b/LightweightCharts/Classes/Implementations/API/Series/AreaSeries.swift deleted file mode 100644 index 44f87bb..0000000 --- a/LightweightCharts/Classes/Implementations/API/Series/AreaSeries.swift +++ /dev/null @@ -1,8 +0,0 @@ -import Foundation - -public class AreaSeries: SeriesObject, SeriesApi { - - public typealias Options = AreaSeriesOptions - public typealias TickValue = LineData - -} diff --git a/LightweightCharts/Classes/Implementations/API/Series/BarSeries.swift b/LightweightCharts/Classes/Implementations/API/Series/BarSeries.swift deleted file mode 100644 index bfc56ce..0000000 --- a/LightweightCharts/Classes/Implementations/API/Series/BarSeries.swift +++ /dev/null @@ -1,8 +0,0 @@ -import Foundation - -public class BarSeries: SeriesObject, SeriesApi { - - public typealias Options = BarSeriesOptions - public typealias TickValue = BarData - -} diff --git a/LightweightCharts/Classes/Implementations/API/Series/CandlestickSeries.swift b/LightweightCharts/Classes/Implementations/API/Series/CandlestickSeries.swift deleted file mode 100644 index 41fa2a4..0000000 --- a/LightweightCharts/Classes/Implementations/API/Series/CandlestickSeries.swift +++ /dev/null @@ -1,8 +0,0 @@ -import Foundation - -public class CandlestickSeries: SeriesObject, SeriesApi { - - public typealias Options = CandlestickSeriesOptions - public typealias TickValue = BarData - -} diff --git a/LightweightCharts/Classes/Implementations/API/Series/HistogramSeries.swift b/LightweightCharts/Classes/Implementations/API/Series/HistogramSeries.swift deleted file mode 100644 index 41425b3..0000000 --- a/LightweightCharts/Classes/Implementations/API/Series/HistogramSeries.swift +++ /dev/null @@ -1,8 +0,0 @@ -import Foundation - -public class HistogramSeries: SeriesObject, SeriesApi { - - public typealias Options = HistogramSeriesOptions - public typealias TickValue = HistogramData - -} diff --git a/LightweightCharts/Classes/Implementations/API/Series/LineSeries.swift b/LightweightCharts/Classes/Implementations/API/Series/LineSeries.swift deleted file mode 100644 index 01b0e4e..0000000 --- a/LightweightCharts/Classes/Implementations/API/Series/LineSeries.swift +++ /dev/null @@ -1,8 +0,0 @@ -import Foundation - -public class LineSeries: SeriesObject, SeriesApi { - - public typealias Options = LineSeriesOptions - public typealias TickValue = LineData - -} diff --git a/LightweightCharts/Classes/Implementations/API/Series/SeriesApi+Extension.swift b/LightweightCharts/Classes/Implementations/API/Series/SeriesApi+Extension.swift deleted file mode 100644 index fdf2254..0000000 --- a/LightweightCharts/Classes/Implementations/API/Series/SeriesApi+Extension.swift +++ /dev/null @@ -1,112 +0,0 @@ -import Foundation - -public extension SeriesApi where Self: SeriesObject { - - func priceFormatter() -> PriceFormatterApi { - let priceFormatter = PriceFormatter(context: context) - let script = "var \(priceFormatter.jsName) = \(jsName).priceFormatter();" - context.evaluateScript(script) { _, _ in - } - return priceFormatter - } - - func coordinateToPrice(coordinate: Double, completion: @escaping (BarPrice?) -> Void) { - let script = "\(jsName).coordinateToPrice(\(coordinate));" - context.evaluateScript(script) { (result, _) in - completion(result as? BarPrice) - } - } - - func priceToCoordinate(price: Double, completion: @escaping (Coordinate?) -> Void) { - let script = "\(jsName).priceToCoordinate(\(price));" - context.evaluateScript(script) { (result, _) in - completion(result as? Coordinate) - } - } - - func barsInLogicalRange(range: FromToRange, completion: @escaping (BarsInfo?) -> Void) { - let script = "\(jsName).setData(\(range.jsonString));" - context.decodedResult(forScript: script, completion: completion) - } - - func applyOptions(options: Options) { - let optionsScript = options.optionsScript(for: closureStore) - let script = """ - \(optionsScript.options) - \(jsName).applyOptions(\(optionsScript.variableName)); - """ - context.evaluateScript(script, completion: nil) - } - - func options(completion: @escaping (Options?) -> Void) { - let script = "\(jsName).options();" - context.decodedResult(forScript: script, completion: completion) - } - - func priceScale() -> PriceScaleApi { - let priceScale = PriceScale(context: context) - let script = "var \(priceScale.jsName) = \(jsName).priceScale();" - context.evaluateScript(script) { _, _ in - } - return priceScale - } - - func setData(data: [TickValue]) { - setSeriesData(data) - } - - func update(bar: TickValue) { - updateSeriesBar(bar) - } - - func setData(data: [WhitespaceData]) { - setSeriesData(data) - } - - func update(bar: WhitespaceData) { - updateSeriesBar(bar) - } - - func setData(data: [SeriesDataType]) { - setSeriesData(data) - } - - func update(bar: SeriesDataType) { - updateSeriesBar(bar) - } - - func setMarkers(data: [SeriesMarker]) { - let script = "\(jsName).setMarkers(\(data.jsonString));" - context.evaluateScript(script, completion: nil) - } - - func createPriceLine(options: PriceLineOptions?) -> PriceLine { - let priceLine = PriceLine(context: context) - let options = options ?? PriceLineOptions() - let script = "var \(priceLine.jsName) = \(jsName).createPriceLine(\(options.jsonString));" - context.evaluateScript(script, completion: nil) - return priceLine - } - - func removePriceLine(line: PriceLine) { - let script = "\(jsName).removePriceLine(\(line.jsName));" - context.evaluateScript(script, completion: nil) - } - - func seriesType(completion: @escaping (SeriesType?) -> Void) { - let script = "\(jsName).seriesType();" - context.decodedResult(forScript: script, completion: completion) - } - - private func setSeriesData(_ data: [T]) { - let script = "\(jsName).setData(\(data.jsonString));" - context.evaluateScript(script, completion: nil) - } - - private func updateSeriesBar(_ bar: T) { - let script = "\(jsName).update(\(bar.jsonString));" - context.evaluateScript(script, completion: nil) - } - - -} diff --git a/LightweightCharts/Classes/Implementations/API/Series/SeriesObject.swift b/LightweightCharts/Classes/Implementations/API/Series/SeriesObject.swift deleted file mode 100644 index 346e4c2..0000000 --- a/LightweightCharts/Classes/Implementations/API/Series/SeriesObject.swift +++ /dev/null @@ -1,18 +0,0 @@ -import Foundation - -public class SeriesObject: JavaScriptObject { - - static var name: String { String(describing: self) } - - let jsName: String - - unowned var context: JavaScriptEvaluator - weak var closureStore: ClosuresStore? - - required init(context: JavaScriptEvaluator, closureStore: ClosuresStore?) { - self.context = context - self.closureStore = closureStore - self.jsName = Self.name + .uniqueString - } - -} diff --git a/LightweightCharts/Classes/Implementations/API/TimeScale.swift b/LightweightCharts/Classes/Implementations/API/TimeScale.swift deleted file mode 100644 index 11061b5..0000000 --- a/LightweightCharts/Classes/Implementations/API/TimeScale.swift +++ /dev/null @@ -1,188 +0,0 @@ -import Foundation - -public protocol TimeScaleDelegate: AnyObject { - - func didVisibleTimeRangeChange(onTimeScale timeScale: TimeScaleApi, parameters: TimeRange?) - func didVisibleLogicalRangeChange(onTimeScale timeScale: TimeScaleApi, parameters: LogicalRange?) - -} - -// MARK: - -class TimeScale: JavaScriptObject { - - typealias Context = JavaScriptEvaluator & JavaScriptMessageProducer - - let jsName = "timeScale" + .uniqueString - - weak var delegate: TimeScaleDelegate? - - private weak var context: Context? - weak var closureStore: ClosuresStore? - private let messageHandler: MessageHandler - - init(context: Context, closureStore: ClosuresStore?) { - self.context = context - self.closureStore = closureStore - messageHandler = MessageHandler() - messageHandler.delegate = self - } - - private func subsriberScript(forName name: String, subscription: Subscription) -> String { - switch subscription { - case .crosshairMove, .click: - return "var \(name) = subscriberCrosshairMoveAndClickFunction('\(name)');" - default: - return "var \(name) = postMessageFunction('\(name)');" - } - } - - private func subscriberName(for subsription: Subscription) -> String { - return "\(subsription.rawValue)_\(jsName)" - } - - private func subscribe(subscription: Subscription) { - let name = subscriberName(for: subscription) - let subscriberScript = subsriberScript(forName: name, subscription: subscription) - let script = subscriberScript + "\n\(jsName).subscribe\(subscription.jsRepresentation)(\(name));" - context?.addMessageHandler(messageHandler, name: name) - context?.evaluateScript(script, completion: nil) - } - - private func unsubscribe(subsription: Subscription) { - let name = subscriberName(for: subsription) - let script = "\(jsName).unsubscribe\(subsription.jsRepresentation)(\(name));" - context?.evaluateScript(script, completion: nil) - } - -} - -// MARK: - TimeScaleApi -extension TimeScale: TimeScaleApi { - - func scrollPosition(completion: @escaping (Double?) -> Void) { - let script = "\(jsName).scrollPosition();" - context?.evaluateScript(script) { (result, _) in - completion(result as? Double) - } - } - - func scrollToPosition(position: Double, animated: Bool) { - let script = "\(jsName).scrollToPosition(\(position), \(animated));" - context?.evaluateScript(script, completion: nil) - } - - func scrollToRealTime() { - let script = "\(jsName).scrollToRealTime();" - context?.evaluateScript(script, completion: nil) - } - - func getVisibleRange(completion: @escaping (TimeRange?) -> Void) { - let script = "\(jsName).getVisibleRange();" - context?.decodedResult(forScript: script, completion: completion) - } - - func setVisibleRange(range: TimeRange) { - let script = "\(jsName).setVisibleRange(\(range.jsonString));" - context?.evaluateScript(script, completion: nil) - } - - func getVisibleLogicalRange(completion: @escaping (LogicalRange?) -> Void) { - let script = "\(jsName).getVisibleLogicalRange();" - context?.decodedResult(forScript: script, completion: completion) - } - - func setVisibleLogicalRange(range: FromToRange) { - let script = "\(jsName).setVisibleLogicalRange(\(range.jsonString));" - context?.evaluateScript(script, completion: nil) - } - - func resetTimeScale() { - let script = "\(jsName).resetTimeScale();" - context?.evaluateScript(script, completion: nil) - } - - func fitContent() { - let script = "\(jsName).fitContent();" - context?.evaluateScript(script, completion: nil) - } - - func logicalToCoordinate(logical: Logical, completion: @escaping (Coordinate?) -> Void) { - let script = "\(jsName).logicalToCoordinate(\(logical));" - context?.evaluateScript(script) { (result, _) in - completion(result as? Coordinate) - } - } - - func coordinateToLogical(x: Double, completion: @escaping (Logical?) -> Void) { - let script = "\(jsName).coordinateToLogical(\(x));" - context?.evaluateScript(script) { (result, _) in - completion(result as? Logical) - } - } - - func timeToCoordinate(time: Time, completion: @escaping (Coordinate?) -> Void) { - let script = "\(jsName).timeToCoordinate(\(time.jsonString));" - context?.evaluateScript(script) { (result, _) in - completion(result as? Coordinate) - } - } - - func coordinateToTime(x: Double, completion: @escaping (Time?) -> Void) { - let script = "\(jsName).coordinateToTime(\(x));" - context?.decodedResult(forScript: script, completion: completion) - } - - func subscribeVisibleTimeRangeChange() { - subscribe(subscription: .visibleTimeRangeChange) - } - - func unsubscribeVisibleTimeRangeChange() { - unsubscribe(subsription: .visibleTimeRangeChange) - } - - func subscribeVisibleLogicalRangeChange() { - subscribe(subscription: .visibleLogicalRangeChange) - } - - func unsubscribeVisibleLogicalRangeChange() { - unsubscribe(subsription: .visibleLogicalRangeChange) - } - - func applyOptions(options: TimeScaleOptions) { - let optionsScript = options.optionsScript(for: closureStore) - let script = """ - \(optionsScript.options) - \(jsName).applyOptions(\(optionsScript.variableName)); - """ - context?.evaluateScript(script, completion: nil) - } - - func options(completion: @escaping (TimeScaleOptions?) -> Void) { - let script = "\(jsName).options();" - context?.decodedResult(forScript: script, completion: completion) - } - -} - -// MARK: - MessageHandlerDelegate -extension TimeScale: MessageHandlerDelegate { - - func messageHandler(_ messageHandler: MessageHandler, - didReceiveClickWithParameters parameters: MouseEventParams) { - } - - func messageHandler(_ messageHandler: MessageHandler, - didReceiveCrosshairMoveWithParameters parameters: MouseEventParams) { - } - - func messageHandler(_ messageHandler: MessageHandler, - didReceiveVisibleTimeRangeChangeWithParameters parameters: TimeRange?) { - delegate?.didVisibleTimeRangeChange(onTimeScale: self, parameters: parameters) - } - - func messageHandler(_ messageHandler: MessageHandler, - didReceiveVisibleLogicalRangeChangeWithParameters parameters: LogicalRange?) { - delegate?.didVisibleLogicalRangeChange(onTimeScale: self, parameters: parameters) - } - -} diff --git a/LightweightCharts/Classes/Implementations/JavaScriptEvaluator.swift b/LightweightCharts/Classes/Implementations/JavaScriptEvaluator.swift deleted file mode 100644 index 0d0f7e0..0000000 --- a/LightweightCharts/Classes/Implementations/JavaScriptEvaluator.swift +++ /dev/null @@ -1,12 +0,0 @@ -import Foundation -import WebKit - -protocol JavaScriptEvaluator: AnyObject { - - func evaluateScript(_ script: String, completion: ((Any?, Error?) -> Void)?) - func decodedResult(forScript script: String, completion: @escaping (T?) -> Void) - func evaluate(script: String, - resultType: T.Type, - completion: @escaping (Result) -> Void) - -} diff --git a/LightweightCharts/Classes/Implementations/JavaScriptMessageProducer.swift b/LightweightCharts/Classes/Implementations/JavaScriptMessageProducer.swift deleted file mode 100644 index 016cc16..0000000 --- a/LightweightCharts/Classes/Implementations/JavaScriptMessageProducer.swift +++ /dev/null @@ -1,8 +0,0 @@ -import Foundation -import WebKit - -protocol JavaScriptMessageProducer: AnyObject { - - func addMessageHandler(_ messageHandler: WKScriptMessageHandler, name: String) - -} diff --git a/LightweightCharts/Classes/Implementations/JavaScriptObject.swift b/LightweightCharts/Classes/Implementations/JavaScriptObject.swift deleted file mode 100644 index 65fa1bf..0000000 --- a/LightweightCharts/Classes/Implementations/JavaScriptObject.swift +++ /dev/null @@ -1,5 +0,0 @@ -protocol JavaScriptObject: AnyObject { - - var jsName: String { get } - -} diff --git a/LightweightCharts/Classes/Implementations/Subscription/MessageHandler.swift b/LightweightCharts/Classes/Implementations/Subscription/MessageHandler.swift deleted file mode 100644 index fe0ecee..0000000 --- a/LightweightCharts/Classes/Implementations/Subscription/MessageHandler.swift +++ /dev/null @@ -1,60 +0,0 @@ -import Foundation -import WebKit - -protocol MessageHandlerDelegate: AnyObject { - - func messageHandler(_ messageHandler: MessageHandler, - didReceiveClickWithParameters parameters: MouseEventParams) - func messageHandler(_ messageHandler: MessageHandler, - didReceiveCrosshairMoveWithParameters parameters: MouseEventParams) - func messageHandler(_ messageHandler: MessageHandler, - didReceiveVisibleTimeRangeChangeWithParameters parameters: TimeRange?) - func messageHandler(_ messageHandler: MessageHandler, - didReceiveVisibleLogicalRangeChangeWithParameters parameters: LogicalRange?) -} - -// MARK: - -class MessageHandler: NSObject { - - weak var delegate: MessageHandlerDelegate? - - private func decode(_ jsonString: String) throws -> T { - do { - let data = jsonString.data(using: .utf8)! - return try JSONDecoder().decode(T.self, from: data) - } catch { - throw error - } - } - -} - -// MARK: - WKScriptMessageHandler -extension MessageHandler: WKScriptMessageHandler { - - func userContentController(_ userContentController: WKUserContentController, - didReceive message: WKScriptMessage) { - let nameComponents = message.name.components(separatedBy: "_") - if let namePrefix = nameComponents.first, - let subscription = Subscription(rawValue: namePrefix) { - guard let messageBodyJSONString = message.body as? String else { return } - switch subscription { - case .click: - if let parameters: MouseEventParams = try? decode(messageBodyJSONString) { - delegate?.messageHandler(self, didReceiveClickWithParameters: parameters) - } - case .crosshairMove: - if let parameters: MouseEventParams = try? decode(messageBodyJSONString) { - delegate?.messageHandler(self, didReceiveCrosshairMoveWithParameters: parameters) - } - case .visibleTimeRangeChange: - let parameters: TimeRange? = try? decode(messageBodyJSONString) - delegate?.messageHandler(self, didReceiveVisibleTimeRangeChangeWithParameters: parameters) - case .visibleLogicalRangeChange: - let parameters: LogicalRange? = try? decode(messageBodyJSONString) - delegate?.messageHandler(self, didReceiveVisibleLogicalRangeChangeWithParameters: parameters) - } - } - } - -} diff --git a/LightweightCharts/Classes/Implementations/Subscription/Subscription.swift b/LightweightCharts/Classes/Implementations/Subscription/Subscription.swift deleted file mode 100644 index 961f0a1..0000000 --- a/LightweightCharts/Classes/Implementations/Subscription/Subscription.swift +++ /dev/null @@ -1,22 +0,0 @@ -import Foundation - -enum Subscription: String { - case click = "ClickSubscriber" - case crosshairMove = "CrosshairMoveSubscriber" - case visibleTimeRangeChange = "VisibleTimeRangeChangeSubscriber" - case visibleLogicalRangeChange = "VisibleLogicalRangeChangeSubscriber" - - var jsRepresentation: String { - switch self { - case .click: - return "Click" - case .crosshairMove: - return "CrosshairMove" - case .visibleTimeRangeChange: - return "VisibleTimeRangeChange" - case .visibleLogicalRangeChange: - return "VisibleLogicalRangeChange" - } - } - -} diff --git a/LightweightCharts/Classes/Implementations/SyncScriptEvaluating/JavaScriptMethod.swift b/LightweightCharts/Classes/Implementations/SyncScriptEvaluating/JavaScriptMethod.swift deleted file mode 100644 index 5ba12f0..0000000 --- a/LightweightCharts/Classes/Implementations/SyncScriptEvaluating/JavaScriptMethod.swift +++ /dev/null @@ -1,76 +0,0 @@ -import Foundation - -public enum JavaScriptMethod { - case javaScript(String) - case closure((Input) -> Output) -} - -// MARK: - JavaScriptSyncMethod -extension JavaScriptMethod: JavaScriptSyncMethod { - - struct Payload: Decodable { - let params: T - } - - func evaluate(payloadData: Data, with decoder: JSONDecoder) -> String { - var result = "" - if case let .closure(closure) = self, - let payload = try? decoder.decode(Payload.self, from: payloadData) { - let output = closure(payload.params) - result = (output as? String) ?? output.jsonString - } - return result - } - -} - -// MARK: - JSFunction -struct JSFunction { - - enum PromptFunction { - - case simpleFormatter - case tickMarkFormatter - case autoscaleInfoProvider - - var name: String { - switch self { - case .simpleFormatter: - return "promptFunction" - case .tickMarkFormatter: - return "promptTickMarkFormatterFunction" - case .autoscaleInfoProvider: - return "promptAutoscaleInfoProviderFunction" - } - } - - } - - let name = "function" + .uniqueString - let function: JavaScriptMethod - - private let promptFunctionName: String - - init(prompt: PromptFunction = .simpleFormatter, function: JavaScriptMethod) { - self.function = function - self.promptFunctionName = prompt.name - } - - init(prompt: PromptFunction = .simpleFormatter, closure: @escaping (Input) -> Output) { - self.init(prompt: prompt, function: .closure(closure)) - } - - init(prompt: PromptFunction = .simpleFormatter, javaScript: String) { - self.init(prompt: prompt, function: .javaScript(javaScript)) - } - - func script() -> String { - switch function { - case let .javaScript(javaScript): - return javaScript - case .closure: - return "\(promptFunctionName)('\(name)');" - } - } - -} diff --git a/LightweightCharts/Classes/Implementations/SyncScriptEvaluating/JavaScriptSyncMethod.swift b/LightweightCharts/Classes/Implementations/SyncScriptEvaluating/JavaScriptSyncMethod.swift deleted file mode 100644 index 1a2856b..0000000 --- a/LightweightCharts/Classes/Implementations/SyncScriptEvaluating/JavaScriptSyncMethod.swift +++ /dev/null @@ -1,7 +0,0 @@ -import Foundation - -protocol JavaScriptSyncMethod { - - func evaluate(payloadData: Data, with decoder: JSONDecoder) -> String - -} diff --git a/LightweightCharts/Classes/Implementations/SyncScriptEvaluating/PromptHandler.swift b/LightweightCharts/Classes/Implementations/SyncScriptEvaluating/PromptHandler.swift deleted file mode 100644 index 370079f..0000000 --- a/LightweightCharts/Classes/Implementations/SyncScriptEvaluating/PromptHandler.swift +++ /dev/null @@ -1,51 +0,0 @@ -import Foundation -import WebKit - -protocol ClosuresStore: AnyObject { - - func addMethod(_ method: JavaScriptMethod, forName name: String) - -} - -// MARK: - -class PromptHandler: NSObject, ClosuresStore { - - private let decoder = JSONDecoder() - - private var closures: [String: JavaScriptSyncMethod] = [:] - - func addMethod(_ method: JavaScriptMethod, forName name: String) where Input: Decodable { - switch method { - case .closure: - closures[name] = method - case .javaScript: - break - } - } - -} - -// MARK: - WKUIDelegate -extension PromptHandler: WKUIDelegate { - - struct Payload: Decodable { - let object: String - } - - func webView( - _ webView: WKWebView, - runJavaScriptTextInputPanelWithPrompt prompt: String, - defaultText: String?, - initiatedByFrame frame: WKFrameInfo, - completionHandler: @escaping (String?) -> Void) { - - if let payloadData = prompt.data(using: .utf8, allowLossyConversion: false), - let payload = try? decoder.decode(Payload.self, from: payloadData) { - let result = closures[payload.object]?.evaluate(payloadData: payloadData, with: decoder) - completionHandler(result) - } else { - completionHandler(defaultText) - } - } - -} diff --git a/LightweightCharts/Classes/Implementations/WebView.swift b/LightweightCharts/Classes/Implementations/WebView.swift deleted file mode 100644 index fb4098a..0000000 --- a/LightweightCharts/Classes/Implementations/WebView.swift +++ /dev/null @@ -1,77 +0,0 @@ -import WebKit - -public protocol JavaScriptErrorDelegate: AnyObject { - - func didFailEvaluateScript(_ script: String, withError error: Error) - -} - -// MARK: - -class WebView: WKWebView { - - weak var errorDelegate: JavaScriptErrorDelegate? - -} - -// MARK: - JavaScriptEvaluator -extension WebView: JavaScriptEvaluator { - - func evaluateScript(_ script: String, completion: ((Any?, Error?) -> Void)?) { - evaluateJavaScript(script) { [weak self] (result, error) in - if let error = error { - self?.errorDelegate?.didFailEvaluateScript(script, withError: error) - } - completion?(result, error) - } - } - - func decodedResult(forScript script: String, completion: @escaping (T?) -> Void) { - let jsonStringifiedScrpt = "var scriptResult = \(script); JSON.stringify(scriptResult);" - evaluate(script: jsonStringifiedScrpt, resultType: T.self) { result in - switch result { - case let .success(model): - completion(model) - case .failure: - completion(nil) - } - } - } - - func evaluate(script: String, - resultType: T.Type, - completion: @escaping (Result) -> Void) { - evaluateJavaScript(script) { (scriptResult, error) in - if let error = error { - self.errorDelegate?.didFailEvaluateScript(script, withError: error) - completion(.failure(error)) - return - } - do { - let jsonString = (scriptResult as? String) ?? "" - let jsonData = jsonString.data(using: .utf8) ?? Data() - let result: T = try self.decodeResult(jsonData) - completion(.success(result)) - } catch { - completion(.failure(error)) - } - } - } - - private func decodeResult(_ data: Data) throws -> T { - do { - return try JSONDecoder().decode(T.self, from: data) - } catch { - throw error - } - } - -} - -// MARK: - JavaScriptMessageProducer -extension WebView: JavaScriptMessageProducer { - - func addMessageHandler(_ messageHandler: WKScriptMessageHandler, name: String) { - configuration.userContentController.add(messageHandler, name: name) - } - -} diff --git a/LightweightCharts/Classes/LightweightChartsModels/AutoscaleInfoProvider.swift b/LightweightCharts/Classes/LightweightChartsModels/AutoscaleInfoProvider.swift deleted file mode 100644 index dc9678c..0000000 --- a/LightweightCharts/Classes/LightweightChartsModels/AutoscaleInfoProvider.swift +++ /dev/null @@ -1,66 +0,0 @@ -import Foundation - -public struct AutoscaleInfoProvider { - - public var function: JavaScriptMethod? { jsFunction?.function } - - let jsFunction: JSFunction? - - public init(_ function: JavaScriptMethod) { - self.jsFunction = JSFunction(prompt: .autoscaleInfoProvider, function: function) - } - -} - -// MARK: - Codable -extension AutoscaleInfoProvider: Codable { - - public func encode(to encoder: Encoder) throws { - } - - public init(from decoder: Decoder) throws { - jsFunction = nil - } - -} - -// MARK: - -public struct AutoScaleMargins: Codable { - - /** The number of pixels for bottom margin */ - public var below: Double? - /** The number of pixels for top margin */ - public var above: Double? - - public init(below: Double? = nil, above: Double? = nil) { - self.below = below - self.above = above - } - -} - -// MARK: - -public struct AutoscaleInfo: Codable { - - public var priceRange: PriceRange? - public var margins: AutoScaleMargins? - - public init(priceRange: PriceRange? = nil, margins: AutoScaleMargins? = nil) { - self.priceRange = priceRange - self.margins = margins - } - -} - -// MARK: - -public struct PriceRange: Codable { - - public var minValue: Double? - public var maxValue: Double? - - public init(minValue: Double? = nil, maxValue: Double? = nil) { - self.minValue = minValue - self.maxValue = maxValue - } - -} diff --git a/LightweightCharts/Classes/LightweightChartsModels/AxisPressedMouseMoveOptions.swift b/LightweightCharts/Classes/LightweightChartsModels/AxisPressedMouseMoveOptions.swift deleted file mode 100644 index dec3e52..0000000 --- a/LightweightCharts/Classes/LightweightChartsModels/AxisPressedMouseMoveOptions.swift +++ /dev/null @@ -1,13 +0,0 @@ -import Foundation - -public struct AxisPressedMouseMoveOptions: Codable { - - public var time: Bool? - public var price: Bool? - - public init(time: Bool? = nil, price: Bool? = nil) { - self.time = time - self.price = price - } - -} diff --git a/LightweightCharts/Classes/LightweightChartsModels/BarPrice.swift b/LightweightCharts/Classes/LightweightChartsModels/BarPrice.swift deleted file mode 100644 index 4bee92a..0000000 --- a/LightweightCharts/Classes/LightweightChartsModels/BarPrice.swift +++ /dev/null @@ -1,3 +0,0 @@ -import Foundation - -public typealias BarPrice = Double diff --git a/LightweightCharts/Classes/LightweightChartsModels/BarsInfo.swift b/LightweightCharts/Classes/LightweightChartsModels/BarsInfo.swift deleted file mode 100644 index cbff7cc..0000000 --- a/LightweightCharts/Classes/LightweightChartsModels/BarsInfo.swift +++ /dev/null @@ -1,17 +0,0 @@ -import Foundation - -public struct BarsInfo: Codable { - - public var from: Time? - public var to: Time? - public var barsBefore: Double? - public var barsAfter: Double? - - public init(from: Time? = nil, to: Time? = nil, barsBefore: Double? = nil, barsAfter: Double? = nil) { - self.from = from - self.to = to - self.barsBefore = barsBefore - self.barsAfter = barsAfter - } - -} diff --git a/LightweightCharts/Classes/LightweightChartsModels/BusinessDay.swift b/LightweightCharts/Classes/LightweightChartsModels/BusinessDay.swift deleted file mode 100644 index bec9c21..0000000 --- a/LightweightCharts/Classes/LightweightChartsModels/BusinessDay.swift +++ /dev/null @@ -1,15 +0,0 @@ -import Foundation - -public struct BusinessDay: Codable { - - public let year: Int - public let month: Int - public let day: Int - - public init(year: Int, month: Int, day: Int) { - self.year = year - self.month = month - self.day = day - } - -} diff --git a/LightweightCharts/Classes/LightweightChartsModels/ChartColor.swift b/LightweightCharts/Classes/LightweightChartsModels/ChartColor.swift deleted file mode 100644 index f0f3ada..0000000 --- a/LightweightCharts/Classes/LightweightChartsModels/ChartColor.swift +++ /dev/null @@ -1,203 +0,0 @@ -import Foundation -import UIKit - -public final class ChartColor: UIColor { - - public convenience init(_ color: UIColor) { - self.init(colorComponents: color.components) - } - - convenience init(colorComponents: ColorComponents) { - self.init( - red: colorComponents.red, - green: colorComponents.green, - blue: colorComponents.blue, - alpha: colorComponents.alpha - ) - } - -} - -// MARK: - Codable -extension ChartColor: Codable { } - -// MARK: - RawRepresentable -extension ChartColor: RawRepresentable { - - public var rawValue: String { - let components = self.components - return "rgba(\(components.red255), \(components.green255), \(components.blue255), \(components.alpha))" - } - - public convenience init(rawValue: String) { - guard let colorComponents = ColorComponents.from(string: rawValue) else { - self.init(colorComponents: .clear) - return - } - self.init( - red: colorComponents.red, - green: colorComponents.green, - blue: colorComponents.blue, - alpha: colorComponents.alpha - ) - } - -} - -// MARK: - ExpressibleByStringLiteral -extension ChartColor: ExpressibleByStringLiteral { - - public convenience init(stringLiteral value: String) { - self.init(rawValue: value) - } - -} - -// MARK: - -struct ColorComponents { - var red: CGFloat - var green: CGFloat - var blue: CGFloat - var alpha: CGFloat - - var red255: Int { Int(colorComponent: red) } - var green255: Int { Int(colorComponent: green) } - var blue255: Int { Int(colorComponent: blue) } - - init( - red: CGFloat = 0, - green: CGFloat = 0, - blue: CGFloat = 0, - alpha: CGFloat = 0 - ) { - self.red = red - self.green = green - self.blue = blue - self.alpha = alpha - } - -} - -// MARK: - -extension ColorComponents { - - static func from(string: String) -> ColorComponents? { - let range = NSRange(string.startIndex.. ColorComponents? { - guard let match = NSRegularExpression.rgba?.firstMatch(in: rgbaString, range: range) else { return nil } - guard match.numberOfRanges >= 5 else { return nil } - - guard let red = parse(componentMatch: match, at: 1, in: rgbaString) else { return nil } - guard let green = parse(componentMatch: match, at: 2, in: rgbaString) else { return nil } - guard let blue = parse(componentMatch: match, at: 3, in: rgbaString) else { return nil } - guard let alpha = parse(componentMatch: match, at: 4, in: rgbaString) else { return nil } - - return ColorComponents( - red: red / 255.0, - green: green / 255.0, - blue: blue / 255.0, - alpha: alpha - ) - } - - static func parse(rgbString: String, range: NSRange) -> ColorComponents? { - guard let match = NSRegularExpression.rgb?.firstMatch(in: rgbString, range: range) else { return nil } - guard match.numberOfRanges >= 4 else { return nil } - - guard let red = parse(componentMatch: match, at: 1, in: rgbString) else { return nil } - guard let green = parse(componentMatch: match, at: 2, in: rgbString) else { return nil } - guard let blue = parse(componentMatch: match, at: 3, in: rgbString) else { return nil } - - return ColorComponents( - red: red / 255.0, - green: green / 255.0, - blue: blue / 255.0, - alpha: 1.0 - ) - } - - static func parse(componentMatch: NSTextCheckingResult, at index: Int, in string: String) -> CGFloat? { - guard let range = Range(componentMatch.range(at: index), in: string) else { return nil } - guard let value = Float(string[range]) else { return nil } - return CGFloat(value) - } - - static func parse(hexString: String) -> ColorComponents? { - if hexString.hasPrefix("#") { - return parse(hexString: String(hexString.dropFirst())) - } - - let scanner = Scanner(string: hexString) - var hexNumber: UInt64 = 0 - - guard scanner.scanHexInt64(&hexNumber) else { return nil } - - switch hexString.count { - case 3: return ColorComponents.from(hex3: hexNumber) // #RGB - case 4: return ColorComponents.from(hex4: hexNumber) // #RGBA - case 6: return ColorComponents.from(hex6: hexNumber) // #RRGGBB - case 8: return ColorComponents.from(hex8: hexNumber) // #RRGGBBAA - default: return nil - } - } - - /// #RGB hex - static func from(hex3: UInt64) -> ColorComponents { - return ColorComponents( - red: CGFloat((hex3 & 0xf00) >> 8) / 15, - green: CGFloat((hex3 & 0x0f0) >> 4) / 15, - blue: CGFloat(hex3 & 0x00f) / 15, - alpha: 1 - ) - } - - /// #RGBA hex - static func from(hex4: UInt64) -> ColorComponents { - return ColorComponents( - red: CGFloat((hex4 & 0xf000) >> 12) / 15, - green: CGFloat((hex4 & 0x0f00) >> 8) / 15, - blue: CGFloat((hex4 & 0x00f0) >> 4) / 15, - alpha: CGFloat(hex4 & 0x000f) / 15 - ) - } - - /// #RRGGBB hex - static func from(hex6: UInt64) -> ColorComponents { - return ColorComponents( - red: CGFloat((hex6 & 0xff0000) >> 16) / 255, - green: CGFloat((hex6 & 0x00ff00) >> 8) / 255, - blue: CGFloat(hex6 & 0x0000ff) / 255, - alpha: 1 - ) - } - - /// #RRGGBBAA hex - static func from(hex8: UInt64) -> ColorComponents { - return ColorComponents( - red: CGFloat((hex8 & 0xff000000) >> 24) / 255, - green: CGFloat((hex8 & 0x00ff0000) >> 16) / 255, - blue: CGFloat((hex8 & 0x0000ff00) >> 8) / 255, - alpha: CGFloat(hex8 & 0x000000ff) / 255 - ) - } - -} - -// MARK: - -extension ColorComponents { - - static var clear: ColorComponents { ColorComponents() } - -} diff --git a/LightweightCharts/Classes/LightweightChartsModels/ColorType.swift b/LightweightCharts/Classes/LightweightChartsModels/ColorType.swift deleted file mode 100644 index 46ffb96..0000000 --- a/LightweightCharts/Classes/LightweightChartsModels/ColorType.swift +++ /dev/null @@ -1,6 +0,0 @@ -import Foundation - -public enum ColorType: String, Codable { - case solid = "solid" - case verticalGradient = "gradient" -} diff --git a/LightweightCharts/Classes/LightweightChartsModels/Coordinate.swift b/LightweightCharts/Classes/LightweightChartsModels/Coordinate.swift deleted file mode 100644 index dd0b2bf..0000000 --- a/LightweightCharts/Classes/LightweightChartsModels/Coordinate.swift +++ /dev/null @@ -1,3 +0,0 @@ -import Foundation - -public typealias Coordinate = Double diff --git a/LightweightCharts/Classes/LightweightChartsModels/Data/SeriesData/BarData.swift b/LightweightCharts/Classes/LightweightChartsModels/Data/SeriesData/BarData.swift deleted file mode 100644 index d37abcd..0000000 --- a/LightweightCharts/Classes/LightweightChartsModels/Data/SeriesData/BarData.swift +++ /dev/null @@ -1,31 +0,0 @@ -import Foundation - -protocol BarSeriesData: SeriesData { - - var time: Time { get } - - var open: Double? { get } - var high: Double? { get } - var low: Double? { get } - var close: Double? { get } - -} - -// MARK: - -public struct BarData: BarSeriesData { - - public var time: Time - public var open: Double? - public var high: Double? - public var low: Double? - public var close: Double? - - public init(time: Time, open: Double?, high: Double?, low: Double?, close: Double?) { - self.time = time - self.open = open - self.high = high - self.low = low - self.close = close - } - -} diff --git a/LightweightCharts/Classes/LightweightChartsModels/Data/SeriesData/HistogramData.swift b/LightweightCharts/Classes/LightweightChartsModels/Data/SeriesData/HistogramData.swift deleted file mode 100644 index 9fdbcf0..0000000 --- a/LightweightCharts/Classes/LightweightChartsModels/Data/SeriesData/HistogramData.swift +++ /dev/null @@ -1,28 +0,0 @@ -import Foundation - -/** -Structure describing a single item of data for histogram series -*/ -protocol HistogramSeriesData: LineSeriesData { - - /** - * Optional color value for certain data item. If missed, color from HistogramSeriesOptions is used - */ - var color: ChartColor? { get } - -} - -// MARK: - -public struct HistogramData: HistogramSeriesData { - - public var color: ChartColor? - public var time: Time - public var value: Double? - - public init(color: ChartColor?, time: Time, value: Double?) { - self.color = color - self.time = time - self.value = value - } - -} diff --git a/LightweightCharts/Classes/LightweightChartsModels/Data/SeriesData/LineData.swift b/LightweightCharts/Classes/LightweightChartsModels/Data/SeriesData/LineData.swift deleted file mode 100644 index aff0aa3..0000000 --- a/LightweightCharts/Classes/LightweightChartsModels/Data/SeriesData/LineData.swift +++ /dev/null @@ -1,26 +0,0 @@ -import Foundation - -protocol LineSeriesData: SeriesData { - - /** - * Price value of data item - */ - var value: Double? { get } - -} - -// MARK: - -/** -* Structure describing single data item for series of type Line or Area -*/ -public struct LineData: LineSeriesData { - - public var time: Time - public var value: Double? - - public init(time: Time, value: Double?) { - self.time = time - self.value = value - } - -} diff --git a/LightweightCharts/Classes/LightweightChartsModels/Data/SeriesData/SeriesData.swift b/LightweightCharts/Classes/LightweightChartsModels/Data/SeriesData/SeriesData.swift deleted file mode 100644 index 6b237b0..0000000 --- a/LightweightCharts/Classes/LightweightChartsModels/Data/SeriesData/SeriesData.swift +++ /dev/null @@ -1,7 +0,0 @@ -import Foundation - -public protocol SeriesData: Codable { - - var time: Time { get } - -} diff --git a/LightweightCharts/Classes/LightweightChartsModels/Data/SeriesData/SeriesDataType.swift b/LightweightCharts/Classes/LightweightChartsModels/Data/SeriesData/SeriesDataType.swift deleted file mode 100644 index d751e59..0000000 --- a/LightweightCharts/Classes/LightweightChartsModels/Data/SeriesData/SeriesDataType.swift +++ /dev/null @@ -1,46 +0,0 @@ -import Foundation - -public enum SeriesDataType: SeriesData where T: SeriesData { - - case data(T) - case whitespace(WhitespaceData) - - public var time: Time { - switch self { - case let .data(data): - return data.time - case let .whitespace(whitespaceData): - return whitespaceData.time - } - } - -} - -// MARK: - Codable -extension SeriesDataType: Codable { - - public init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - if let data = try? container.decode(T.self) { - self = .data(data) - } else if let whitespaceData = try? container.decode(WhitespaceData.self) { - self = .whitespace(whitespaceData) - } else { - throw DecodingError.dataCorruptedError( - in: container, - debugDescription: "Error decoding \(type(of: self))" - ) - } - } - - public func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() - switch self { - case let .data(data): - try container.encode(data) - case let .whitespace(whitespaceData): - try container.encode(whitespaceData) - } - } - -} diff --git a/LightweightCharts/Classes/LightweightChartsModels/Data/SeriesData/WhitespaceData.swift b/LightweightCharts/Classes/LightweightChartsModels/Data/SeriesData/WhitespaceData.swift deleted file mode 100644 index 3db3910..0000000 --- a/LightweightCharts/Classes/LightweightChartsModels/Data/SeriesData/WhitespaceData.swift +++ /dev/null @@ -1,14 +0,0 @@ -import Foundation - -/** - * Structure describing whitespace data item (data point without series' data) - */ -public struct WhitespaceData: SeriesData { - - public var time: Time - - public init(time: Time) { - self.time = time - } - -} diff --git a/LightweightCharts/Classes/LightweightChartsModels/FromToRange.swift b/LightweightCharts/Classes/LightweightChartsModels/FromToRange.swift deleted file mode 100644 index 9a59c20..0000000 --- a/LightweightCharts/Classes/LightweightChartsModels/FromToRange.swift +++ /dev/null @@ -1,25 +0,0 @@ -import Foundation - -public struct FromToRange { - - public var from: T - public var to: T - - public init(from: T, to: T) { - self.from = from - self.to = to - } - -} - -// MARK: - -extension FromToRange: Codable where T: Codable { } - -// MARK: - -public typealias Logical = Double - -// MARK: - -public typealias LogicalRange = FromToRange - -// MARK: - -public typealias TimeRange = FromToRange