diff --git a/example/assets/icons/ic_gauge_chart.svg b/example/assets/icons/ic_gauge_chart.svg new file mode 100644 index 000000000..0147dab82 --- /dev/null +++ b/example/assets/icons/ic_gauge_chart.svg @@ -0,0 +1,3 @@ + + + diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 73a295ecb..395ff459e 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -25,11 +25,11 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/url_launcher_ios/ios" SPEC CHECKSUMS: - Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467 - package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4 + Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 + package_info_plus: 58f0028419748fad15bf008b270aaa8e54380b1c path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe -PODFILE CHECKSUM: 0dbd5a87e0ace00c9610d2037ac22083a01f861d +PODFILE CHECKSUM: c4c93c5f6502fe2754f48404d3594bf779584011 COCOAPODS: 1.16.2 diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index dd83b3827..60a4e286a 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -8,25 +8,14 @@ /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; - 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; + 3A769574DE769ECF798B0709 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 380B38C853A9B1A4CE259991 /* Pods_Runner.framework */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; - E74A93EDB2B26BA3B68EB856 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66E5FD19F03E6633F69A2755 /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ -/* Begin PBXContainerItemProxy section */ - 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 97C146E61CF9000F007C117D /* Project object */; - proxyType = 1; - remoteGlobalIDString = 97C146ED1CF9000F007C117D; - remoteInfo = Runner; - }; -/* End PBXContainerItemProxy section */ - /* Begin PBXCopyFilesBuildPhase section */ 9705A1C41CF9048500538489 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; @@ -43,15 +32,12 @@ /* Begin PBXFileReference section */ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 2533C9FF039E091768C02A3C /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; - 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; - 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 380B38C853A9B1A4CE259991 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 66E5FD19F03E6633F69A2755 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 70B7C328B4B2F1CF5A8F4CD5 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; - 92784C7839A21A123BE5F569 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -59,7 +45,8 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - FDA57114F6B1B00C26C17AEA /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + A5FD4176E495AE357451309C /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + F92DACD635C19D794086368F /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -67,19 +54,29 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - E74A93EDB2B26BA3B68EB856 /* Pods_Runner.framework in Frameworks */, + 3A769574DE769ECF798B0709 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 331C8082294A63A400263BE5 /* RunnerTests */ = { + 387A47388B1D7AAF78141AE7 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 380B38C853A9B1A4CE259991 /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 87E9D592125921BB4FA5096E /* Pods */ = { isa = PBXGroup; children = ( - 331C807B294A618700263BE5 /* RunnerTests.swift */, + 70B7C328B4B2F1CF5A8F4CD5 /* Pods-Runner.debug.xcconfig */, + F92DACD635C19D794086368F /* Pods-Runner.release.xcconfig */, + A5FD4176E495AE357451309C /* Pods-Runner.profile.xcconfig */, ); - path = RunnerTests; + path = Pods; sourceTree = ""; }; 9740EEB11CF90186004384FC /* Flutter */ = { @@ -99,9 +96,8 @@ 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, - 331C8082294A63A400263BE5 /* RunnerTests */, - B5EDA2152F3EE166ACB0102F /* Pods */, - F62F59B1CB0A3441A4333BCE /* Frameworks */, + 87E9D592125921BB4FA5096E /* Pods */, + 387A47388B1D7AAF78141AE7 /* Frameworks */, ); sourceTree = ""; }; @@ -109,7 +105,6 @@ isa = PBXGroup; children = ( 97C146EE1CF9000F007C117D /* Runner.app */, - 331C8081294A63A400263BE5 /* RunnerTests.xctest */, ); name = Products; sourceTree = ""; @@ -129,56 +124,21 @@ path = Runner; sourceTree = ""; }; - B5EDA2152F3EE166ACB0102F /* Pods */ = { - isa = PBXGroup; - children = ( - 92784C7839A21A123BE5F569 /* Pods-Runner.debug.xcconfig */, - FDA57114F6B1B00C26C17AEA /* Pods-Runner.release.xcconfig */, - 2533C9FF039E091768C02A3C /* Pods-Runner.profile.xcconfig */, - ); - path = Pods; - sourceTree = ""; - }; - F62F59B1CB0A3441A4333BCE /* Frameworks */ = { - isa = PBXGroup; - children = ( - 66E5FD19F03E6633F69A2755 /* Pods_Runner.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - 331C8080294A63A400263BE5 /* RunnerTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; - buildPhases = ( - 331C807D294A63A400263BE5 /* Sources */, - 331C807F294A63A400263BE5 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 331C8086294A63A400263BE5 /* PBXTargetDependency */, - ); - name = RunnerTests; - productName = RunnerTests; - productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; 97C146ED1CF9000F007C117D /* Runner */ = { isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - 1474CFBDFB72840D91CF260E /* [CP] Check Pods Manifest.lock */, + B16E897CCC57E0F4B2344803 /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - 654E70DC308C8EF6E1C50DAB /* [CP] Embed Pods Frameworks */, + 00C61598CDE2223281B7DB47 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -195,14 +155,9 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - BuildIndependentTargetsInParallel = YES; LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { - 331C8080294A63A400263BE5 = { - CreatedOnToolsVersion = 14.0; - TestTargetID = 97C146ED1CF9000F007C117D; - }; 97C146ED1CF9000F007C117D = { CreatedOnToolsVersion = 7.3.1; LastSwiftMigration = 1100; @@ -223,19 +178,11 @@ projectRoot = ""; targets = ( 97C146ED1CF9000F007C117D /* Runner */, - 331C8080294A63A400263BE5 /* RunnerTests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 331C807F294A63A400263BE5 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; 97C146EC1CF9000F007C117D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -250,26 +197,21 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 1474CFBDFB72840D91CF260E /* [CP] Check Pods Manifest.lock */ = { + 00C61598CDE2223281B7DB47 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; + name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { @@ -288,49 +230,46 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; - 654E70DC308C8EF6E1C50DAB /* [CP] Embed Pods Frameworks */ = { + 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + inputPaths = ( ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + name = "Run Script"; + outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; - 9740EEB61CF901F6004384FC /* Run Script */ = { + B16E897CCC57E0F4B2344803 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( ); - name = "Run Script"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 331C807D294A63A400263BE5 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 97C146EA1CF9000F007C117D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -342,14 +281,6 @@ }; /* End PBXSourcesBuildPhase section */ -/* Begin PBXTargetDependency section */ - 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 97C146ED1CF9000F007C117D /* Runner */; - targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - /* Begin PBXVariantGroup section */ 97C146FA1CF9000F007C117D /* Main.storyboard */ = { isa = PBXVariantGroup; @@ -374,7 +305,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -404,7 +334,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -413,7 +342,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -453,7 +382,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -483,7 +411,6 @@ DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -498,7 +425,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -510,7 +437,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -540,7 +466,6 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -549,7 +474,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -615,45 +540,9 @@ }; name = Release; }; - B5628A0E2E53D3C1005A9E21 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - PRODUCT_NAME = RunnerTests; - }; - name = Debug; - }; - B5628A0F2E53D3C1005A9E21 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - PRODUCT_NAME = RunnerTests; - }; - name = Release; - }; - B5628A102E53D3C1005A9E21 /* Profile */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = RunnerTests; - }; - name = Profile; - }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - B5628A0E2E53D3C1005A9E21 /* Debug */, - B5628A0F2E53D3C1005A9E21 /* Release */, - B5628A102E53D3C1005A9E21 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index e3773d42e..4003b03e4 100644 --- a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -61,7 +61,6 @@ ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" debugServiceExtension = "internal" - enableGPUValidationMode = "1" allowLocationSimulation = "YES"> diff --git a/example/lib/presentation/resources/app_assets.dart b/example/lib/presentation/resources/app_assets.dart index 08da1e7e4..52b0f75db 100644 --- a/example/lib/presentation/resources/app_assets.dart +++ b/example/lib/presentation/resources/app_assets.dart @@ -15,6 +15,8 @@ class AppAssets { return 'assets/icons/ic_radar_chart.svg'; case ChartType.candlestick: return 'assets/icons/ic_candle_chart.svg'; + case ChartType.gauge: + return 'assets/icons/ic_gauge_chart.svg'; } } diff --git a/example/lib/presentation/resources/app_colors.dart b/example/lib/presentation/resources/app_colors.dart index a1ca589a1..8303202ac 100644 --- a/example/lib/presentation/resources/app_colors.dart +++ b/example/lib/presentation/resources/app_colors.dart @@ -11,9 +11,11 @@ class AppColors { static const Color mainGridLineColor = Colors.white10; static const Color borderColor = Colors.white54; static const Color gridLinesColor = Color(0x11FFFFFF); + static const Color grey = Color(0xFFD9D9D9); static const Color contentColorBlack = Colors.black; static const Color contentColorWhite = Colors.white; + static const Color contentColorWhite12 = Colors.white12; static const Color contentColorBlue = Color(0xFF2196F3); static const Color contentColorYellow = Color(0xFFFFC300); static const Color contentColorOrange = Color(0xFFFF683B); diff --git a/example/lib/presentation/samples/bar/bar_chart_sample1.dart b/example/lib/presentation/samples/bar/bar_chart_sample1.dart index e3d736394..de276d715 100644 --- a/example/lib/presentation/samples/bar/bar_chart_sample1.dart +++ b/example/lib/presentation/samples/bar/bar_chart_sample1.dart @@ -138,18 +138,17 @@ class BarChartSample1State extends State { } List showingGroups() => List.generate( - 7, - (i) => switch (i) { - 0 => makeGroupData(0, 5, isTouched: i == touchedIndex), - 1 => makeGroupData(1, 6.5, isTouched: i == touchedIndex), - 2 => makeGroupData(2, 5, isTouched: i == touchedIndex), - 3 => makeGroupData(3, 7.5, isTouched: i == touchedIndex), - 4 => makeGroupData(4, 9, isTouched: i == touchedIndex), - 5 => makeGroupData(5, 11.5, isTouched: i == touchedIndex), - 6 => makeGroupData(6, 6.5, isTouched: i == touchedIndex), - _ => throw Error(), - } - ); + 7, + (i) => switch (i) { + 0 => makeGroupData(0, 5, isTouched: i == touchedIndex), + 1 => makeGroupData(1, 6.5, isTouched: i == touchedIndex), + 2 => makeGroupData(2, 5, isTouched: i == touchedIndex), + 3 => makeGroupData(3, 7.5, isTouched: i == touchedIndex), + 4 => makeGroupData(4, 9, isTouched: i == touchedIndex), + 5 => makeGroupData(5, 11.5, isTouched: i == touchedIndex), + 6 => makeGroupData(6, 6.5, isTouched: i == touchedIndex), + _ => throw Error(), + }); BarChartData mainBarData() { return BarChartData( diff --git a/example/lib/presentation/samples/chart_sample.dart b/example/lib/presentation/samples/chart_sample.dart index ea1eef1ac..fc05e4087 100644 --- a/example/lib/presentation/samples/chart_sample.dart +++ b/example/lib/presentation/samples/chart_sample.dart @@ -46,3 +46,9 @@ class CandlestickChartSample extends ChartSample { @override ChartType get type => ChartType.candlestick; } + +class GaugeChartSample extends ChartSample { + GaugeChartSample(super.number, super.builder); + @override + ChartType get type => ChartType.gauge; +} diff --git a/example/lib/presentation/samples/chart_samples.dart b/example/lib/presentation/samples/chart_samples.dart index c848f4bee..1f2d34c84 100644 --- a/example/lib/presentation/samples/chart_samples.dart +++ b/example/lib/presentation/samples/chart_samples.dart @@ -1,4 +1,7 @@ import 'package:fl_chart_app/presentation/samples/candlestick/candlestick_chart_sample1.dart'; +import 'package:fl_chart_app/presentation/samples/gauge/gauge_chart_sample1.dart'; +import 'package:fl_chart_app/presentation/samples/gauge/gauge_chart_sample3.dart'; +import 'package:fl_chart_app/presentation/samples/gauge/gauge_chart_sample4.dart'; import 'package:fl_chart_app/util/app_helper.dart'; import 'bar/bar_chart_sample1.dart'; @@ -10,6 +13,7 @@ import 'bar/bar_chart_sample6.dart'; import 'bar/bar_chart_sample7.dart'; import 'bar/bar_chart_sample8.dart'; import 'chart_sample.dart'; +import 'gauge/gauge_chart_sample2.dart'; import 'line/line_chart_sample1.dart'; import 'line/line_chart_sample10.dart'; import 'line/line_chart_sample11.dart'; @@ -73,6 +77,12 @@ class ChartSamples { ], ChartType.candlestick: [ CandlestickChartSample(1, (context) => const CandlestickChartSample1()), - ] + ], + ChartType.gauge: [ + GaugeChartSample(1, (context) => const GaugeChartSample1()), + GaugeChartSample(2, (context) => const GaugeChartSample2()), + GaugeChartSample(3, (context) => const GaugeChartSample3()), + GaugeChartSample(4, (context) => const GaugeChartSample4()), + ], }; } diff --git a/example/lib/presentation/samples/gauge/gauge_chart_sample1.dart b/example/lib/presentation/samples/gauge/gauge_chart_sample1.dart new file mode 100644 index 000000000..99436ca5e --- /dev/null +++ b/example/lib/presentation/samples/gauge/gauge_chart_sample1.dart @@ -0,0 +1,191 @@ +import 'dart:math'; +import 'dart:ui'; + +import 'package:fl_chart/fl_chart.dart'; +import 'package:fl_chart_app/presentation/resources/app_resources.dart'; +import 'package:flutter/material.dart'; + +class GaugeChartSample1 extends StatefulWidget { + const GaugeChartSample1({super.key}); + + @override + State createState() => GaugeChartSample1State(); +} + +class GaugeChartSample1State extends State { + double _value = 0.5; + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(28), + child: Column( + children: [ + SizedBox( + width: 250, + height: 250, + child: Stack( + children: [ + GaugeChart( + GaugeChartData.progress( + value: _value, + color: AppColors.contentColorPurple, + width: 30, + backgroundColor: + AppColors.contentColorPurple.withValues(alpha: 0.2), + startDegreeOffset: -200, + sweepAngle: 220, + touchData: GaugeTouchData(enabled: true), + ticks: GaugeTicks( + position: GaugeTickPosition.center, + count: 11, + offset: 0, + painter: _MyCustomGaugeMinMaxTickPainter( + color: AppColors.contentColorWhite, + radius: 5, + minIndex: 2, + maxIndex: 8, + minMaxLineLength: 40, + minMaxLineStrokeWidth: 4, + ), + checkToShowTick: GaugeTicks.hideEndpoints, + ), + pointers: [ + // Needle extending from center toward the current value. + GaugePointer( + value: _value, + painter: GaugePointerNeedlePainter( + length: 88, + width: 20, + tailLength: 40, + color: AppColors.contentColorWhite, + ), + ), + // Pivot cap sitting at the gauge center, on top of the + // needle's base — just a second pointer with a small + // circle painter (anchorRadius: 0). + GaugePointer( + value: 0.3, + painter: GaugePointerCirclePainter( + radius: 24, + color: AppColors.contentColorBlack, + strokeWidth: 2, + strokeColor: AppColors.contentColorWhite, + ), + ), + ], + ), + ), + Center( + child: Text( + "${(_value * 100).toInt()}", + style: TextStyle( + color: AppColors.contentColorWhite, + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + ) + ], + ), + ), + Slider(value: _value, onChanged: (v) => setState(() => _value = v)), + ], + ), + ); + } +} + +class _MyCustomGaugeMinMaxTickPainter extends GaugeTickCirclePainter { + _MyCustomGaugeMinMaxTickPainter({ + super.color, + super.radius, + required this.minIndex, + required this.maxIndex, + required this.minMaxLineLength, + required this.minMaxLineStrokeWidth, + this.textOffset = 6, + this.minTextStyle = const TextStyle( + color: Colors.green, + fontSize: 12, + fontWeight: FontWeight.bold, + ), + this.maxTextStyle = const TextStyle( + color: Colors.red, + fontSize: 12, + fontWeight: FontWeight.bold, + ), + }) : super(); + + final int minIndex; + final int maxIndex; + final double minMaxLineLength; + final double minMaxLineStrokeWidth; + final double textOffset; + final TextStyle minTextStyle; + final TextStyle maxTextStyle; + + final _paint = Paint(); + + @override + void draw(Canvas canvas, GaugeTickInfo tickInfo) { + super.draw(canvas, tickInfo); + + if (tickInfo.index != minIndex && tickInfo.index != maxIndex) { + return; + } + final isMin = tickInfo.index == minIndex; + final text = isMin ? "Min" : "Max"; + final textStyle = isMin ? minTextStyle : maxTextStyle; + final rotation = isMin ? pi : 0.0; + final textPainter = TextPainter( + text: TextSpan(text: text, style: textStyle), + textDirection: TextDirection.ltr, + )..layout(); + // 180 degrees + canvas.rotate(rotation); + final offsetX = isMin + ? 0 + textPainter.width + textOffset + : 0 - textPainter.width - minMaxLineLength / 2 - textOffset; + textPainter.paint(canvas, Offset(offsetX, 0 - textPainter.height / 2)); + _paint.color = textStyle.color!; + _paint.strokeWidth = minMaxLineStrokeWidth; + canvas.drawLine( + Offset(0 - minMaxLineLength / 2, 0), + Offset(0 + minMaxLineLength / 2, 0), + _paint, + ); + } + + @override + GaugeTickPainter lerp(GaugeTickPainter b, double t) { + if (b is! _MyCustomGaugeMinMaxTickPainter) { + return b; + } + return _MyCustomGaugeMinMaxTickPainter( + color: Color.lerp(color, b.color, t)!, + radius: lerpDouble(radius, b.radius, t)!, + minIndex: minIndex, + maxIndex: maxIndex, + minMaxLineLength: lerpDouble(minMaxLineLength, b.minMaxLineLength, t)!, + minMaxLineStrokeWidth: + lerpDouble(minMaxLineStrokeWidth, b.minMaxLineStrokeWidth, t)!, + textOffset: lerpDouble(textOffset, b.textOffset, t)!, + minTextStyle: TextStyle.lerp(minTextStyle, b.minTextStyle, t)!, + maxTextStyle: TextStyle.lerp(maxTextStyle, b.maxTextStyle, t)!, + ); + } + + @override + List get props => + [ + super.props, + minIndex, + maxIndex, + minMaxLineLength, + minMaxLineStrokeWidth, + textOffset, + minTextStyle, + maxTextStyle, + ]; +} diff --git a/example/lib/presentation/samples/gauge/gauge_chart_sample2.dart b/example/lib/presentation/samples/gauge/gauge_chart_sample2.dart new file mode 100644 index 000000000..8cd9d5e25 --- /dev/null +++ b/example/lib/presentation/samples/gauge/gauge_chart_sample2.dart @@ -0,0 +1,140 @@ +import 'package:fl_chart/fl_chart.dart'; +import 'package:fl_chart_app/presentation/resources/app_resources.dart'; +import 'package:flutter/material.dart'; + +/// Multi-ring ("Apple Watch"-style) gauge. Three concentric progress +/// rings, each tracking its own value against the same 0..1 scale. +/// Sections are listed innermost-first; the slider drives the +/// innermost ring, the outer two are fixed. +class GaugeChartSample2 extends StatefulWidget { + const GaugeChartSample2({super.key}); + + @override + State createState() => _GaugeChartSample2State(); +} + +class _GaugeChartSample2State extends State { + int _touchedRingIndex = -1; + + static const _items = <(double, Color)>[ + (20, AppColors.contentColorPink), + (40, AppColors.contentColorRed), + (55, AppColors.contentColorOrange), + (70, AppColors.contentColorGreen), + (95, AppColors.contentColorBlue), + ]; + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(28), + child: SizedBox( + width: 250, + height: 250, + child: Stack( + children: [ + GaugeChart( + GaugeChartData( + minValue: 0, + maxValue: 100, + startDegreeOffset: -225, + sweepAngle: 270, + defaultRingWidth: 20, + ringsSpace: 4, + rings: _items.asMap().entries.map((e) { + final index = e.key; + final value = e.value.$1; + Color color = e.value.$2; + if (_touchedRingIndex != -1) { + color = index == _touchedRingIndex + ? color.withValues(alpha: 1) + : color.withValues(alpha: 0.3); + } + return GaugeProgressRing( + value: value, + color: color, + backgroundColor: AppColors.contentColorWhite12, + strokeCap: StrokeCap.round, + ); + }).toList(), + touchData: GaugeTouchData( + enabled: true, + touchCallback: _onTouchCallback, + ), + ), + ), + Align( + alignment: Alignment(0, 0.75), + child: _TouchedRingAnimatedText( + value: _touchedRingIndex != -1 + ? _items[_touchedRingIndex].$1.toInt() + : 0, + color: _touchedRingIndex != -1 + ? _items[_touchedRingIndex].$2 + : AppColors.contentColorWhite12, + ), + ), + ], + ), + ), + ); + } + + void _onTouchCallback(FlTouchEvent event, GaugeTouchResponse? response) { + setState(() { + final touchedRing = response?.touchedRing; + if (event.isInterestedForInteractions && touchedRing != null) { + _touchedRingIndex = touchedRing.touchedRingIndex; + } else { + _touchedRingIndex = -1; + } + }); + } +} + +class _TouchedRingAnimatedText extends ImplicitlyAnimatedWidget { + final int value; + final Color color; + + const _TouchedRingAnimatedText({ + required this.value, + required this.color, + super.duration = const Duration(milliseconds: 250), + }); + + @override + ImplicitlyAnimatedWidgetState<_TouchedRingAnimatedText> createState() => + _TouchedRingAnimatedTextState(); +} + +class _TouchedRingAnimatedTextState + extends AnimatedWidgetBaseState<_TouchedRingAnimatedText> { + IntTween? _valueTween; + ColorTween? _colorTween; + + @override + void forEachTween(TweenVisitor visitor) { + _valueTween = visitor( + _valueTween, + widget.value, + (dynamic value) => IntTween(begin: value as int), + ) as IntTween; + _colorTween = visitor( + _colorTween, + widget.color, + (dynamic value) => ColorTween(begin: value as Color), + ) as ColorTween; + } + + @override + Widget build(BuildContext context) { + return Text( + _valueTween!.evaluate(animation).toInt().toString(), + style: TextStyle( + fontSize: 32, + color: _colorTween!.evaluate(animation), + ), + ); + } +} + diff --git a/example/lib/presentation/samples/gauge/gauge_chart_sample3.dart b/example/lib/presentation/samples/gauge/gauge_chart_sample3.dart new file mode 100644 index 000000000..737dec826 --- /dev/null +++ b/example/lib/presentation/samples/gauge/gauge_chart_sample3.dart @@ -0,0 +1,101 @@ +import 'package:fl_chart/fl_chart.dart'; +import 'package:fl_chart_app/presentation/resources/app_colors.dart'; +import 'package:flutter/material.dart'; + +/// Speedometer-style gauge combining two ring types: +/// - an inner [GaugeProgressRing] showing the current measurement +/// (350..value filled green, rest greyed out) +/// - an outer [GaugeZonesRing] painting fixed threshold bands +/// (350-600 red, 600-700 amber, 700-800 light green, 800-850 green) +/// +/// Touching the gauge reports which ring was hit and, for the zones +/// ring, which specific zone the touch angle falls in. +class GaugeChartSample3 extends StatefulWidget { + const GaugeChartSample3({super.key}); + + @override + State createState() => GaugeChartSample3State(); +} + +class GaugeChartSample3State extends State { + double _value = 717; + + static const _minValue = 350.0; + static const _maxValue = 850.0; + + static const _colorRanges = <(double to, Color color)>[ + (550, AppColors.contentColorRed), + (700, AppColors.contentColorYellow), + (850, AppColors.contentColorGreen), + ]; + + @override + Widget build(BuildContext context) { + Color barColor = _colorRanges.firstWhere((e) => _value <= e.$1).$2; + + return Padding( + padding: const EdgeInsets.all(28), + child: Column( + children: [ + SizedBox( + width: 280, + height: 180, + child: GaugeChart( + GaugeChartData( + minValue: _minValue, + maxValue: _maxValue, + startDegreeOffset: 180, + sweepAngle: 180, + ringsSpace: 6, + rings: [ + // Inner ring — measurement, rounded tip looks good + GaugeProgressRing( + value: _value, + color: barColor, + backgroundColor: AppColors.contentColorWhite12, + width: 30, + strokeCap: StrokeCap.round, + ), + // Outer ring — rounded zones separated by a visible + // gap. zonesSpace is pixels along the arc, uniformly + // deducted from both ends of each zone. With round + // caps each cap extends width/2 beyond the arc, so + // effective visible gap ≈ zonesSpace - width. + GaugeZonesRing( + width: 8, + zonesSpace: 16, + zones: _colorRanges.asMap().entries.map((e) { + final index = e.key; + final to = e.value.$1; + final color = e.value.$2; + final from = index == 0 ? 350.0 : _colorRanges[index - 1].$1; + return GaugeZone( + from: from, + to: to, + color: color, + strokeCap: StrokeCap.round, + ); + }).toList(), + ), + ], + ), + ), + ), + const SizedBox(height: 12), + Center( + child: Text( + _value.toStringAsFixed(0), + style: Theme.of(context).textTheme.headlineSmall, + ), + ), + Slider( + value: _value, + min: _minValue, + max: _maxValue, + onChanged: (v) => setState(() => _value = v), + ), + ], + ), + ); + } +} diff --git a/example/lib/presentation/samples/gauge/gauge_chart_sample4.dart b/example/lib/presentation/samples/gauge/gauge_chart_sample4.dart new file mode 100644 index 000000000..a9d77f35f --- /dev/null +++ b/example/lib/presentation/samples/gauge/gauge_chart_sample4.dart @@ -0,0 +1,114 @@ +import 'package:fl_chart/fl_chart.dart'; +import 'package:fl_chart_app/presentation/resources/app_colors.dart'; +import 'package:flutter/material.dart'; + +class GaugeChartSample4 extends StatefulWidget { + const GaugeChartSample4({super.key}); + + @override + State createState() => _GaugeChartSample4State(); +} + +class _GaugeChartSample4State extends State { + + double _value = 0.35; + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.only( + left: 28, + right: 28, + top: 80, + bottom: 28, + ), + child: Column( + children: [ + SizedBox( + width: 280, + height: 280, + child: GaugeChart( + GaugeChartData( + startDegreeOffset: -200, + sweepAngle: 220, + ringsSpace: 6, + rings: [ + GaugeZonesRing( + width: 100, + zonesSpace: 4, + zones: [ + GaugeZone( + from: 0, + to: 0.25, + color: AppColors.contentColorRed, + ), + GaugeZone( + from: 0.25, + to: 0.50, + color: AppColors.contentColorOrange, + ), + GaugeZone( + from: 0.50, + to: 0.75, + color: AppColors.contentColorYellow, + ), + GaugeZone( + from: 0.75, + to: 1.0, + color: AppColors.contentColorGreen, + ), + ], + ), + ], + ticks: GaugeTicks( + count: 11, + offset: 8, + painter: const GaugeTickLinePainter( + length: 10, + thickness: 2, + color: AppColors.contentColorWhite, + ), + labelBuilder: (v) => (v * 100).toStringAsFixed(0), + labelStyle: const TextStyle( + fontSize: 12, + color: AppColors.contentColorWhite, + fontWeight: FontWeight.w600, + ), + labelOffset: 4, + ), + pointers: [ + // Needle extending from center toward the current value. + GaugePointer( + value: _value, + painter: GaugePointerNeedlePainter( + length: 80, + width: 10, + tailLength: 24, + color: AppColors.contentColorWhite, + ), + ), + // Pivot cap sitting at the gauge center, on top of the + // needle's base — just a second pointer with a small + // circle painter (anchorRadius: 0). + GaugePointer( + value: 0.65, + painter: GaugePointerCirclePainter( + radius: 8, + color: AppColors.contentColorBlack, + strokeWidth: 2, + strokeColor: AppColors.contentColorWhite, + ), + ), + ], + ), + ), + ), + Slider( + value: _value, + onChanged: (v) => setState(() => _value = v), + ) + ], + ), + ); + } +} diff --git a/example/lib/presentation/samples/pie/pie_chart_sample3.dart b/example/lib/presentation/samples/pie/pie_chart_sample3.dart index 7aed34ea2..431a74337 100644 --- a/example/lib/presentation/samples/pie/pie_chart_sample3.dart +++ b/example/lib/presentation/samples/pie/pie_chart_sample3.dart @@ -56,82 +56,78 @@ class PieChartSample3State extends State { const shadows = [Shadow(color: Colors.black, blurRadius: 2)]; return switch (i) { - 0 => - PieChartSectionData( - color: AppColors.contentColorBlue, - value: 40, - title: '40%', - radius: radius, - titleStyle: TextStyle( - fontSize: fontSize, - fontWeight: FontWeight.bold, - color: const Color(0xffffffff), - shadows: shadows, - ), - badgeWidget: _Badge( - 'assets/icons/ophthalmology-svgrepo-com.svg', - size: widgetSize, - borderColor: AppColors.contentColorBlack, - ), - badgePositionPercentageOffset: .98, + 0 => PieChartSectionData( + color: AppColors.contentColorBlue, + value: 40, + title: '40%', + radius: radius, + titleStyle: TextStyle( + fontSize: fontSize, + fontWeight: FontWeight.bold, + color: const Color(0xffffffff), + shadows: shadows, ), - 1 => - PieChartSectionData( - color: AppColors.contentColorYellow, - value: 30, - title: '30%', - radius: radius, - titleStyle: TextStyle( - fontSize: fontSize, - fontWeight: FontWeight.bold, - color: const Color(0xffffffff), - shadows: shadows, - ), - badgeWidget: _Badge( - 'assets/icons/librarian-svgrepo-com.svg', - size: widgetSize, - borderColor: AppColors.contentColorBlack, - ), - badgePositionPercentageOffset: .98, + badgeWidget: _Badge( + 'assets/icons/ophthalmology-svgrepo-com.svg', + size: widgetSize, + borderColor: AppColors.contentColorBlack, ), - 2 => - PieChartSectionData( - color: AppColors.contentColorPurple, - value: 16, - title: '16%', - radius: radius, - titleStyle: TextStyle( - fontSize: fontSize, - fontWeight: FontWeight.bold, - color: const Color(0xffffffff), - shadows: shadows, - ), - badgeWidget: _Badge( - 'assets/icons/fitness-svgrepo-com.svg', - size: widgetSize, - borderColor: AppColors.contentColorBlack, - ), - badgePositionPercentageOffset: .98, + badgePositionPercentageOffset: .98, + ), + 1 => PieChartSectionData( + color: AppColors.contentColorYellow, + value: 30, + title: '30%', + radius: radius, + titleStyle: TextStyle( + fontSize: fontSize, + fontWeight: FontWeight.bold, + color: const Color(0xffffffff), + shadows: shadows, + ), + badgeWidget: _Badge( + 'assets/icons/librarian-svgrepo-com.svg', + size: widgetSize, + borderColor: AppColors.contentColorBlack, + ), + badgePositionPercentageOffset: .98, + ), + 2 => PieChartSectionData( + color: AppColors.contentColorPurple, + value: 16, + title: '16%', + radius: radius, + titleStyle: TextStyle( + fontSize: fontSize, + fontWeight: FontWeight.bold, + color: const Color(0xffffffff), + shadows: shadows, ), - 3 => - PieChartSectionData( - color: AppColors.contentColorGreen, - value: 15, - title: '15%', - radius: radius, - titleStyle: TextStyle( - fontSize: fontSize, - fontWeight: FontWeight.bold, - color: const Color(0xffffffff), - shadows: shadows, - ), - badgeWidget: _Badge( - 'assets/icons/worker-svgrepo-com.svg', - size: widgetSize, - borderColor: AppColors.contentColorBlack, - ), - badgePositionPercentageOffset: .98, + badgeWidget: _Badge( + 'assets/icons/fitness-svgrepo-com.svg', + size: widgetSize, + borderColor: AppColors.contentColorBlack, ), + badgePositionPercentageOffset: .98, + ), + 3 => PieChartSectionData( + color: AppColors.contentColorGreen, + value: 15, + title: '15%', + radius: radius, + titleStyle: TextStyle( + fontSize: fontSize, + fontWeight: FontWeight.bold, + color: const Color(0xffffffff), + shadows: shadows, + ), + badgeWidget: _Badge( + 'assets/icons/worker-svgrepo-com.svg', + size: widgetSize, + borderColor: AppColors.contentColorBlack, + ), + badgePositionPercentageOffset: .98, + ), _ => throw StateError('Invalid'), }; }); @@ -139,7 +135,8 @@ class PieChartSample3State extends State { } class _Badge extends StatelessWidget { - const _Badge(this.svgAsset, { + const _Badge( + this.svgAsset, { required this.size, required this.borderColor, }); diff --git a/example/lib/util/app_helper.dart b/example/lib/util/app_helper.dart index 02b29e867..a455d0dc1 100644 --- a/example/lib/util/app_helper.dart +++ b/example/lib/util/app_helper.dart @@ -1,7 +1,7 @@ import 'package:fl_chart_app/presentation/resources/app_resources.dart'; import 'package:fl_chart_app/urls.dart'; -enum ChartType { line, bar, pie, scatter, radar, candlestick } +enum ChartType { line, bar, pie, scatter, radar, candlestick, gauge } extension ChartTypeExtension on ChartType { String get displayName => '$simpleName Chart'; @@ -13,6 +13,7 @@ extension ChartTypeExtension on ChartType { ChartType.scatter => 'Scatter', ChartType.radar => 'Radar', ChartType.candlestick => 'Candlestick', + ChartType.gauge => 'Gauge', }; String get documentationUrl => Urls.getChartDocumentationUrl(this); diff --git a/lib/fl_chart.dart b/lib/fl_chart.dart index efc2e1e9e..d26b48eb5 100644 --- a/lib/fl_chart.dart +++ b/lib/fl_chart.dart @@ -8,6 +8,8 @@ export 'src/chart/base/base_chart/base_chart_data.dart'; export 'src/chart/base/base_chart/fl_touch_event.dart'; export 'src/chart/candlestick_chart/candlestick_chart.dart'; export 'src/chart/candlestick_chart/candlestick_chart_data.dart'; +export 'src/chart/gauge_chart/gauge_chart.dart'; +export 'src/chart/gauge_chart/gauge_chart_data.dart'; export 'src/chart/line_chart/line_chart.dart'; export 'src/chart/line_chart/line_chart_data.dart'; export 'src/chart/pie_chart/pie_chart.dart'; diff --git a/lib/src/chart/gauge_chart/gauge_chart.dart b/lib/src/chart/gauge_chart/gauge_chart.dart new file mode 100644 index 000000000..7264c0107 --- /dev/null +++ b/lib/src/chart/gauge_chart/gauge_chart.dart @@ -0,0 +1,59 @@ +import 'package:fl_chart/src/chart/gauge_chart/gauge_chart_data.dart'; +import 'package:fl_chart/src/chart/gauge_chart/gauge_chart_renderer.dart'; +import 'package:flutter/widgets.dart'; + +class GaugeChart extends ImplicitlyAnimatedWidget { + /// [data] determines how the [GaugeChart] should be look like, + /// when you make any change in the [GaugeChartData], it updates + /// new values with animation, and duration is [swapAnimationDuration]. + /// also you can change the [swapAnimationCurve] + /// which default is [Curves.linear]. + const GaugeChart( + this.data, { + this.chartRendererKey, + super.key, + super.duration = const Duration(milliseconds: 150), + super.curve = Curves.linear, + }); + + /// Determines how the [GaugeChartData] should be look like. + final GaugeChartData data; + + /// We pass this key to our renderers which are supposed to + /// render the chart itself (without anything around the chart). + final Key? chartRendererKey; + + /// Creates a [_GaugeChartState] + @override + _GaugeChartState createState() => _GaugeChartState(); +} + +class _GaugeChartState extends AnimatedWidgetBaseState { + /// we handle under the hood animations (implicit animations) via this tween, + /// it lerps between the old [GaugeChartData] to the new one. + GaugeChartDataTween? _gaugeChartDataTween; + + @override + Widget build(BuildContext context) { + final showingData = _getData(); + + return GaugeChartLeaf( + data: _gaugeChartDataTween!.evaluate(animation), + targetData: showingData, + ); + } + + @override + void forEachTween(TweenVisitor visitor) { + _gaugeChartDataTween = visitor( + _gaugeChartDataTween, + widget.data, + (dynamic value) => + GaugeChartDataTween(begin: value as GaugeChartData, end: widget.data), + ) as GaugeChartDataTween?; + } + + GaugeChartData _getData() { + return widget.data; + } +} diff --git a/lib/src/chart/gauge_chart/gauge_chart_data.dart b/lib/src/chart/gauge_chart/gauge_chart_data.dart new file mode 100644 index 000000000..f100a96d7 --- /dev/null +++ b/lib/src/chart/gauge_chart/gauge_chart_data.dart @@ -0,0 +1,1058 @@ +import 'dart:ui'; + +import 'package:equatable/equatable.dart'; +import 'package:fl_chart/fl_chart.dart'; +import 'package:fl_chart/src/utils/lerp.dart'; +import 'package:flutter/widgets.dart'; + +/// [GaugeChart] needs this class to render itself. +/// +/// A gauge chart is a set of concentric rings drawn along a shared arc. +/// Each [GaugeRing] is one ring on a scale shared by every ring. +/// Sections are stacked innermost-first in list order — so `rings[0]` +/// is the innermost ring and the last entry is the outermost — separated +/// by [ringsSpace] pixels. +/// +/// A ring is one of two shapes: +/// - [GaugeProgressRing] — a ring filled from [minValue] up to its +/// `value`, with an optional `backgroundColor` behind. +/// - [GaugeZonesRing] — a ring divided into fixed colored [GaugeZone]s +/// (threshold bands). Useful for speedometer-style level indicators. +class GaugeChartData extends BaseChartData with EquatableMixin { + GaugeChartData({ + required List rings, + this.minValue = 0.0, + this.maxValue = 1.0, + this.startDegreeOffset = -225.0, + this.sweepAngle = 270.0, + this.direction = GaugeDirection.clockwise, + this.defaultRingWidth = 10.0, + this.ringsSpace = 0.0, + this.ticks, + List pointers = const [], + GaugeTouchData? touchData, + super.borderData, + }) : rings = List.unmodifiable(rings), + pointers = List.unmodifiable(pointers), + gaugeTouchData = touchData ?? GaugeTouchData(), + assert(maxValue > minValue, 'maxValue must be greater than minValue'), + assert( + sweepAngle > 0 && sweepAngle <= 360, + 'sweepAngle must be in (0, 360]', + ), + assert(ringsSpace >= 0, 'ringsSpace must be >= 0') { + for (final ring in rings) { + switch (ring) { + case GaugeProgressRing(): + assert( + ring.value >= minValue && ring.value <= maxValue, + 'GaugeProgressRing.value ${ring.value} is outside ' + '[$minValue, $maxValue]', + ); + case GaugeZonesRing(): + assert( + ring.zones.isNotEmpty, + 'GaugeZonesRing.zones must not be empty', + ); + for (final zone in ring.zones) { + assert( + zone.from >= minValue && zone.to <= maxValue, + 'GaugeZone [${zone.from}, ${zone.to}] is outside ' + '[$minValue, $maxValue]', + ); + } + } + } + } + + /// Convenience factory for the single-ring progress bar use case + /// (battery meter, loading indicator, etc.). Shorthand for a + /// [GaugeChartData] with one [GaugeProgressRing]. + factory GaugeChartData.progress({ + required double value, + required Color color, + required double width, + Color? backgroundColor, + double min = 0.0, + double max = 1.0, + StrokeCap strokeCap = StrokeCap.butt, + double startDegreeOffset = -225.0, + double sweepAngle = 270.0, + GaugeDirection direction = GaugeDirection.clockwise, + GaugeTicks? ticks, + List pointers = const [], + GaugeTouchData? touchData, + FlBorderData? borderData, + }) => + GaugeChartData( + minValue: min, + maxValue: max, + rings: [ + GaugeProgressRing( + value: value.clamp(min, max), + color: color, + width: width, + backgroundColor: backgroundColor, + strokeCap: strokeCap, + ), + ], + defaultRingWidth: width, + startDegreeOffset: startDegreeOffset, + sweepAngle: sweepAngle, + direction: direction, + ticks: ticks, + pointers: pointers, + touchData: touchData, + borderData: borderData, + ); + + /// The rings drawn by the chart, innermost first. + final List rings; + + /// Lower bound of the gauge scale (inclusive). Shared by every ring. + /// default is 0.0 + final double minValue; + + /// Upper bound of the gauge scale (inclusive). Shared by every ring. + /// default is 1.0 + final double maxValue; + + /// Starting angle of the arc, in degrees. 0° points right, matching + /// [PieChartData.startDegreeOffset] and [Canvas.drawArc]. + final double startDegreeOffset; + + /// Length of the arc, in degrees. Must be in (0, 360]. + final double sweepAngle; + + /// Whether the arc travels clockwise or counter-clockwise from + /// [startDegreeOffset]. + final GaugeDirection direction; + + /// Width used for rings that don't specify their own + /// [GaugeRing.width]. + final double defaultRingWidth; + + /// Radial gap in pixels between adjacent rings. + final double ringsSpace; + + /// Optional tick configuration drawn along the gauge's scale. Ticks + /// reference the ring stack as a whole (outer edge of the outermost + /// ring, inner edge of the innermost ring, or radially centered) and + /// are not owned by any individual ring. + final GaugeTicks? ticks; + + /// Pointers drawn on top of the rings. Each [GaugePointer] carries + /// its own `value` on the same scale as the rings; the painter is + /// pre-transformed so `+x` points radially toward that value. Empty + /// by default. + final List pointers; + + /// Touch configuration and callback. + final GaugeTouchData gaugeTouchData; + + /// Resolves the width for [ring], falling back to + /// [defaultRingWidth] when the ring doesn't specify one. + double resolveRingWidth(GaugeRing ring) => ring.width ?? defaultRingWidth; + + @override + List get props => [ + rings, + minValue, + maxValue, + startDegreeOffset, + sweepAngle, + direction, + defaultRingWidth, + ringsSpace, + ticks, + pointers, + gaugeTouchData, + borderData, + ]; + + GaugeChartData copyWith({ + List? rings, + double? minValue, + double? maxValue, + double? startDegreeOffset, + double? sweepAngle, + GaugeDirection? direction, + double? defaultRingWidth, + double? ringsSpace, + GaugeTicks? ticks, + List? pointers, + GaugeTouchData? touchData, + FlBorderData? borderData, + }) => + GaugeChartData( + rings: rings ?? this.rings, + minValue: minValue ?? this.minValue, + maxValue: maxValue ?? this.maxValue, + startDegreeOffset: startDegreeOffset ?? this.startDegreeOffset, + sweepAngle: sweepAngle ?? this.sweepAngle, + direction: direction ?? this.direction, + defaultRingWidth: defaultRingWidth ?? this.defaultRingWidth, + ringsSpace: ringsSpace ?? this.ringsSpace, + ticks: ticks ?? this.ticks, + pointers: pointers ?? this.pointers, + touchData: touchData ?? gaugeTouchData, + borderData: borderData ?? this.borderData, + ); + + @override + GaugeChartData lerp(BaseChartData a, BaseChartData b, double t) { + if (a is GaugeChartData && b is GaugeChartData) { + return GaugeChartData( + rings: lerpGaugeRingList(a.rings, b.rings, t)!, + minValue: lerpDouble(a.minValue, b.minValue, t)!, + maxValue: lerpDouble(a.maxValue, b.maxValue, t)!, + startDegreeOffset: + lerpDouble(a.startDegreeOffset, b.startDegreeOffset, t)!, + sweepAngle: lerpDouble(a.sweepAngle, b.sweepAngle, t)!, + direction: b.direction, + defaultRingWidth: + lerpDouble(a.defaultRingWidth, b.defaultRingWidth, t)!, + ringsSpace: lerpDouble(a.ringsSpace, b.ringsSpace, t)!, + ticks: GaugeTicks.lerp(a.ticks, b.ticks, t), + pointers: lerpGaugePointerList(a.pointers, b.pointers, t)!, + touchData: b.gaugeTouchData, + borderData: FlBorderData.lerp(a.borderData, b.borderData, t), + ); + } else { + throw StateError('Illegal State'); + } + } +} + +/// Base type for a single concentric ring of a [GaugeChartData]. +/// +/// Sealed hierarchy — a ring is always either a [GaugeProgressRing] +/// (filled up to a value) or a [GaugeZonesRing] (divided into fixed +/// [GaugeZone]s). The [GaugeChartPainter] dispatches on the concrete +/// type; the hierarchy is closed to ensure that never changes silently. +sealed class GaugeRing with EquatableMixin { + const GaugeRing({this.width}); + + /// Stroke width in pixels. If null, + /// [GaugeChartData.defaultRingWidth] is used. + final double? width; + + /// Lerps this ring against another. Cross-type lerps snap to [b] + /// (matches the [FlDotPainter.lerp] fallback pattern). + static GaugeRing lerp(GaugeRing a, GaugeRing b, double t) { + if (a is GaugeProgressRing && b is GaugeProgressRing) { + return GaugeProgressRing.lerp(a, b, t); + } + if (a is GaugeZonesRing && b is GaugeZonesRing) { + return GaugeZonesRing.lerp(a, b, t); + } + return b; + } +} + +/// A ring showing progress from [GaugeChartData.minValue] up to [value]. +/// +/// The unfilled portion of the ring (from [value] to +/// [GaugeChartData.maxValue]) is painted in [backgroundColor] when +/// provided; otherwise it's left empty. +final class GaugeProgressRing extends GaugeRing { + const GaugeProgressRing({ + required this.value, + required this.color, + this.backgroundColor, + this.strokeCap = StrokeCap.butt, + super.width, + }) : assert(width == null || width > 0, 'width must be > 0 when provided'); + + /// Current value on the gauge scale. The ring fills from + /// [GaugeChartData.minValue] up to this value. + final double value; + + /// Stroke color for the filled portion of the ring. + final Color color; + + /// Optional stroke color for the unfilled portion. When null, no + /// background is drawn for this ring. + final Color? backgroundColor; + + /// Cap style applied to the ends of both the background and filled + /// arcs of this ring. For the typical battery-meter / progress-bar + /// look, use [StrokeCap.round]. + final StrokeCap strokeCap; + + GaugeProgressRing copyWith({ + double? value, + Color? color, + double? width, + Color? backgroundColor, + StrokeCap? strokeCap, + }) => + GaugeProgressRing( + value: value ?? this.value, + color: color ?? this.color, + width: width ?? this.width, + backgroundColor: backgroundColor ?? this.backgroundColor, + strokeCap: strokeCap ?? this.strokeCap, + ); + + static GaugeProgressRing lerp( + GaugeProgressRing a, + GaugeProgressRing b, + double t, + ) => + GaugeProgressRing( + value: lerpDouble(a.value, b.value, t)!, + color: Color.lerp(a.color, b.color, t)!, + width: lerpDouble(a.width, b.width, t), + backgroundColor: Color.lerp(a.backgroundColor, b.backgroundColor, t), + strokeCap: b.strokeCap, + ); + + @override + List get props => [value, color, width, backgroundColor, strokeCap]; +} + +/// A ring displaying one or more fixed colored [GaugeZone]s along the +/// arc — useful for threshold / level indicators (e.g. a speedometer's +/// red/amber/green bands). +/// +/// Zones are bounds-checked against [GaugeChartData.minValue] / +/// [GaugeChartData.maxValue] but not required to be sorted, contiguous, +/// or non-overlapping. They're drawn in list order, so later zones paint +/// on top of overlapping earlier ones. +final class GaugeZonesRing extends GaugeRing { + const GaugeZonesRing({ + required this.zones, + this.zonesSpace = 0.0, + super.width, + }) : assert(width == null || width > 0, 'width must be > 0 when provided'), + assert(zonesSpace >= 0, 'zonesSpace must be >= 0'); + + /// The colored bands drawn along this ring's arc. Each band controls + /// its own [GaugeZone.strokeCap]. + final List zones; + + /// Visible gap between adjacent zones, in pixels, measured + /// perpendicular to the ring (so the gap has the same width at the + /// inner and outer edges regardless of ring thickness). + /// + /// Applied only *between* zones (in list order): a [zonesSpace]-wide + /// rectangular strip is carved at each internal boundary. The first + /// zone's leading edge and the last zone's trailing edge are not + /// touched, so zones stay flush to the gauge's angular extremes. + /// + /// Per-zone `StrokeCap.round` is preserved: after the strip is + /// carved, each neighbor's internal end is re-drawn as a filled + /// circle so zones with rounded caps keep their pill look across + /// the gap. The visible gap between two rounded neighbors is + /// `zonesSpace − width`, so set `zonesSpace > width` to keep a + /// visible separator when caps are rounded. + final double zonesSpace; + + GaugeZonesRing copyWith({ + List? zones, + double? zonesSpace, + double? width, + }) => + GaugeZonesRing( + zones: zones ?? this.zones, + zonesSpace: zonesSpace ?? this.zonesSpace, + width: width ?? this.width, + ); + + static GaugeZonesRing lerp( + GaugeZonesRing a, + GaugeZonesRing b, + double t, + ) => + GaugeZonesRing( + zones: lerpGaugeZoneList(a.zones, b.zones, t)!, + zonesSpace: lerpDouble(a.zonesSpace, b.zonesSpace, t)!, + width: lerpDouble(a.width, b.width, t), + ); + + @override + List get props => [zones, zonesSpace, width]; +} + +/// A single colored band within a [GaugeZonesRing]. [from] and [to] +/// are positions on the shared [GaugeChartData.minValue] / +/// [GaugeChartData.maxValue] scale; [to] must be `>= from`. +@immutable +class GaugeZone with EquatableMixin { + const GaugeZone({ + required this.from, + required this.to, + required this.color, + this.strokeCap = StrokeCap.butt, + }) : assert(to >= from, 'to must be >= from'); + + final double from; + final double to; + final Color color; + + /// Cap style applied to this band's two ends. Independent per zone — + /// adjacent zones paint in list order, so a later zone's butt start + /// paints over an earlier zone's rounded end-cap bulge. + final StrokeCap strokeCap; + + GaugeZone copyWith({ + double? from, + double? to, + Color? color, + StrokeCap? strokeCap, + }) => + GaugeZone( + from: from ?? this.from, + to: to ?? this.to, + color: color ?? this.color, + strokeCap: strokeCap ?? this.strokeCap, + ); + + static GaugeZone lerp(GaugeZone a, GaugeZone b, double t) => GaugeZone( + from: lerpDouble(a.from, b.from, t)!, + to: lerpDouble(a.to, b.to, t)!, + color: Color.lerp(a.color, b.color, t)!, + strokeCap: b.strokeCap, + ); + + @override + List get props => [from, to, color, strokeCap]; +} + +/// It lerps a [GaugeChartData] to another [GaugeChartData] (handles +/// animation for updating values). +class GaugeChartDataTween extends Tween { + GaugeChartDataTween({ + required GaugeChartData begin, + required GaugeChartData end, + }) : super(begin: begin, end: end); + + /// Lerps a [GaugeChartData] based on [t] value, check [Tween.lerp]. + @override + GaugeChartData lerp(double t) => begin!.lerp(begin!, end!, t); +} + +/// Direction the arc travels from [GaugeChartData.startDegreeOffset]. +enum GaugeDirection { + clockwise, + counterClockwise, +} + +/// Where tick marks sit relative to the gauge's ring stack. +enum GaugeTickPosition { + /// Outside the outermost ring. Reserves radial padding so rings + /// shrink to fit ticks (and labels, when present). + outer, + + /// Inside the innermost ring's inner edge, toward the gauge center. + inner, + + /// Radially centered between the outermost ring's outer edge and + /// the innermost ring's inner edge. + center, +} + +/// Configuration for tick marks drawn along a [GaugeChartData]'s arc. +/// +/// Ticks frame the gauge as a whole — they reference the ring stack's +/// outer / inner envelope, not an individual ring. Evenly spaced along +/// the sweep, with the first tick at [GaugeChartData.startDegreeOffset] +/// and the last at the sweep's end. +/// +/// When [labelBuilder] is provided, a text label is painted radially +/// past each tick. Labels stay upright (not tangent-rotated) for +/// readability. +@immutable +class GaugeTicks with EquatableMixin { + const GaugeTicks({ + this.count = 3, + this.position = GaugeTickPosition.outer, + this.offset = 0, + this.painter = const GaugeTickLinePainter(), + this.checkToShowTick = showAll, + this.labelBuilder, + this.labelStyle, + this.labelOffset = 0, + }) : assert(count >= 2, 'count must be >= 2'); + + /// Number of ticks drawn, including both sweep endpoints. Minimum 2. + final int count; + + /// Where ticks sit relative to the gauge's outer / inner bounds. + final GaugeTickPosition position; + + /// Signed pixel delta from the natural tick anchor, measured along + /// the [position]'s outward axis (away from center for [outer], + /// toward center for [inner], toward outer for [center]). Positive + /// extends the tick farther in that direction; negative pulls it + /// back toward (or across) the ring stack. + final double offset; + + /// Renders each tick. The canvas is pre-translated and pre-rotated + /// so the painter just draws a horizontal, right-facing shape at + /// the origin — see [GaugeTickPainter.draw]. + final GaugeTickPainter painter; + + /// Predicate deciding whether each tick is drawn. Receives a + /// [GaugeTickInfo] with the tick's index, the total [count], its + /// scale value, and the chart's `minValue` / `maxValue`. Returning + /// `false` skips both the tick mark and its label. + /// + /// Defaults to [GaugeTicks.showAll]. Use [GaugeTicks.hideEndpoints] + /// to skip the first and last ticks — handy when the arc already + /// visually anchors its extremes (e.g. rounded zone caps). Users + /// can pass any predicate for custom behaviour. + /// + /// Pass a top-level or static function when possible; anonymous + /// closures compare by identity, which breaks equality across + /// rebuilds and causes unnecessary tween animations. + final CheckToShowGaugeTick checkToShowTick; + + /// Default [CheckToShowGaugeTick] — draws every tick. + static bool showAll(GaugeTickInfo info) => true; + + /// [CheckToShowGaugeTick] that skips the first and last ticks. Equivalent + /// to `info.index != 0 && info.index != info.count - 1`. + static bool hideEndpoints(GaugeTickInfo info) => + info.index != 0 && info.index != info.count - 1; + + /// Returns the text painted as a label next to each tick. The input + /// is the tick's scale value on `[minValue, maxValue]`. When `null`, + /// no labels are drawn. To keep a tick mark but drop its label at a + /// specific value, return an empty string from this builder. + final String Function(double value)? labelBuilder; + + /// Style applied to labels, merged with the chart's current theme. + /// When `null`, the theme's default text style is used. + final TextStyle? labelStyle; + + /// Signed pixel delta between the tick's far edge and its label, + /// along the same outward axis as [offset]. Positive pushes the + /// label further outward; negative pulls it toward (or across) the + /// tick. + final double labelOffset; + + static GaugeTicks? lerp(GaugeTicks? a, GaugeTicks? b, double t) { + if (a == null || b == null) return b; + return GaugeTicks( + count: lerpInt(a.count, b.count, t), + position: b.position, + offset: lerpDouble(a.offset, b.offset, t)!, + painter: a.painter.lerp(b.painter, t), + checkToShowTick: b.checkToShowTick, + labelBuilder: b.labelBuilder, + labelStyle: TextStyle.lerp(a.labelStyle, b.labelStyle, t), + labelOffset: lerpDouble(a.labelOffset, b.labelOffset, t)!, + ); + } + + @override + List get props => [ + count, + position, + offset, + painter, + checkToShowTick, + labelBuilder, + labelStyle, + labelOffset, + ]; +} + +/// Signature for a predicate that decides whether a gauge tick is +/// drawn. See [GaugeTicks.CheckToShowGaugeTick]. +typedef CheckToShowGaugeTick = bool Function(GaugeTickInfo info); + +/// Context passed to [CheckToShowGaugeTick] callbacks. +@immutable +class GaugeTickInfo with EquatableMixin { + const GaugeTickInfo({ + required this.index, + required this.count, + required this.value, + required this.minValue, + required this.maxValue, + }); + + /// Position of this tick in the sweep, `0` for the first tick and + /// `count - 1` for the last. + final int index; + + /// Total number of tick positions, matching [GaugeTicks.count]. + final int count; + + /// Scale value at this tick's position, on `[minValue, maxValue]`. + final double value; + + /// The gauge's minimum scale value ([GaugeChartData.minValue]). + final double minValue; + + /// The gauge's maximum scale value ([GaugeChartData.maxValue]). + final double maxValue; + + @override + List get props => [index, count, value, minValue, maxValue]; +} + +/// Interface for rendering a single tick mark on a [GaugeChart]. +/// +/// The gauge painter pre-translates and pre-rotates the canvas for +/// each tick so implementations never touch trig: `(0, 0)` is the +/// tick's anchor point, the `+x` axis points in the tick's outward +/// direction (see [GaugeTicks.position]), and the `+y` axis is +/// tangent to the arc in the sweep direction. Draw a horizontal, +/// right-facing shape at the origin and the gauge handles placing +/// and rotating it for every tick angle. +/// +/// Mirrors the [FlDotPainter] pattern. Subclass it to draw custom +/// tick shapes or oriented marks. +abstract class GaugeTickPainter with EquatableMixin { + const GaugeTickPainter(); + + /// Draws a single tick in the pre-transformed local frame described + /// in the class docstring. + void draw(Canvas canvas, GaugeTickInfo tickInfo); + + /// Bounding box of the tick in the unrotated local frame. + /// + /// `width` is the radial extent (along `+x`) and is used to reserve + /// outer padding; `height` is the tangential extent (across `+y`). + Size getSize(); + + /// Lerps two painter configurations. Cross-type lerps fall back to + /// [b], matching [FlDotPainter.lerp]. + GaugeTickPainter lerp(GaugeTickPainter b, double t); +} + +/// Default [GaugeTickPainter]: draws a line segment along `+x`, so +/// each tick points radially outward (relative to [GaugeTicks.position]). +class GaugeTickLinePainter extends GaugeTickPainter { + const GaugeTickLinePainter({ + this.length = 6.0, + this.thickness = 2.0, + this.color = const Color(0xFF000000), + }) : assert(length > 0, 'length must be > 0'), + assert(thickness > 0, 'thickness must be > 0'); + + final double length; + final double thickness; + final Color color; + + @override + void draw(Canvas canvas, GaugeTickInfo tickInfo) { + canvas.drawLine( + Offset.zero, + Offset(length, 0), + Paint() + ..color = color + ..strokeWidth = thickness + ..strokeCap = StrokeCap.round + ..isAntiAlias = true, + ); + } + + @override + Size getSize() => Size(length, thickness); + + @override + GaugeTickPainter lerp(GaugeTickPainter b, double t) { + if (b is! GaugeTickLinePainter) { + return b; + } + return GaugeTickLinePainter( + length: lerpDouble(length, b.length, t)!, + thickness: lerpDouble(thickness, b.thickness, t)!, + color: Color.lerp(color, b.color, t)!, + ); + } + + @override + List get props => [length, thickness, color]; +} + +/// [GaugeTickPainter] that draws each tick as a filled circle, +/// optionally with a stroked outline. Rotation-invariant by shape, so +/// it looks identical at every angle. +class GaugeTickCirclePainter extends GaugeTickPainter { + const GaugeTickCirclePainter({ + this.radius = 3.0, + this.color = const Color(0xFF000000), + this.strokeWidth = 0.0, + this.strokeColor = const Color(0xFF000000), + }) : assert(radius > 0, 'radius must be > 0'); + + final double radius; + final Color color; + final double strokeWidth; + final Color strokeColor; + + @override + void draw(Canvas canvas, GaugeTickInfo tickInfo) { + if (strokeWidth > 0 && strokeColor.a != 0) { + canvas.drawCircle( + Offset.zero, + radius + strokeWidth / 2, + Paint() + ..color = strokeColor + ..style = PaintingStyle.stroke + ..strokeWidth = strokeWidth, + ); + } + canvas.drawCircle( + Offset.zero, + radius, + Paint() + ..color = color + ..style = PaintingStyle.fill, + ); + } + + @override + Size getSize() => Size.fromRadius(radius + strokeWidth); + + @override + GaugeTickPainter lerp(GaugeTickPainter b, double t) { + if (b is! GaugeTickCirclePainter) { + return b; + } + return GaugeTickCirclePainter( + radius: lerpDouble(radius, b.radius, t)!, + color: Color.lerp(color, b.color, t)!, + strokeWidth: lerpDouble(strokeWidth, b.strokeWidth, t)!, + strokeColor: Color.lerp(strokeColor, b.strokeColor, t)!, + ); + } + + @override + List get props => [radius, color, strokeWidth, strokeColor]; +} + +/// A single pointer drawn on top of the gauge, indicating a specific +/// [value] on the scale shared by [GaugeChartData.rings]. +/// +/// Pointers are independent — each carries its own [value]. Sync with +/// a ring's value by passing the same variable to both. To render a +/// "pivot cap" under a needle, stack a small [GaugePointerCirclePainter] +/// on top via a second [GaugePointer] in the same list. +@immutable +class GaugePointer with EquatableMixin { + const GaugePointer({ + required this.value, + this.painter = const GaugePointerNeedlePainter(), + }); + + /// Position on the gauge scale the pointer points at. Values outside + /// `[GaugeChartData.minValue, maxValue]` are not asserted — the + /// pointer simply extends past the sweep endpoints. + final double value; + + /// Renders the pointer's shape. The canvas is pre-transformed by + /// the gauge painter — see [GaugePointerPainter.draw]. + final GaugePointerPainter painter; + + GaugePointer copyWith({double? value, GaugePointerPainter? painter}) => + GaugePointer( + value: value ?? this.value, + painter: painter ?? this.painter, + ); + + static GaugePointer lerp(GaugePointer a, GaugePointer b, double t) => + GaugePointer( + value: lerpDouble(a.value, b.value, t)!, + painter: a.painter.lerp(b.painter, t), + ); + + @override + List get props => [value, painter]; +} + +/// Interface for rendering a single [GaugePointer]. +/// +/// The gauge painter pre-translates and pre-rotates the canvas so +/// implementations never touch trigonometry: +/// +/// - origin `(0, 0)` is the **gauge center** +/// - `+x` axis points **radially outward** toward the pointer's value angle +/// - `+y` axis is **tangent** to the arc in the sweep direction +/// +/// Draw a horizontal, right-facing shape at the origin; the gauge +/// rotates and translates the canvas for each pointer's value. +/// +/// Mirrors the [GaugeTickPainter] pattern. Subclass to draw custom +/// pointer shapes. +abstract class GaugePointerPainter with EquatableMixin { + const GaugePointerPainter(); + + /// Draws the pointer in the pre-transformed local frame described + /// in the class docstring. + void draw(Canvas canvas); + + /// Bounding box of the pointer in the unrotated local frame. + /// `width` is the radial extent (along `+x`), `height` is the + /// tangential extent (across `+y`). + Size getSize(); + + /// Lerps two painter configurations. Cross-type lerps fall back to + /// [b], matching [GaugeTickPainter.lerp]. + GaugePointerPainter lerp(GaugePointerPainter b, double t); +} + +/// Default [GaugePointerPainter]: a classic needle shape. +/// +/// Draws a tapered triangle anchored at the gauge center, narrowing +/// to a point at `(length, 0)`. An optional [tailLength] extends a +/// short stub behind the pivot (toward `-x`). +class GaugePointerNeedlePainter extends GaugePointerPainter { + const GaugePointerNeedlePainter({ + this.length = 60.0, + this.width = 8.0, + this.tailLength = 0.0, + this.color = const Color(0xFF000000), + }) : assert(length > 0, 'length must be > 0'), + assert(width > 0, 'width must be > 0'), + assert(tailLength >= 0, 'tailLength must be >= 0'); + + /// Distance from the gauge center to the needle's tip, in pixels. + final double length; + + /// Width of the needle's base (at the pivot), in pixels. + final double width; + + /// Optional stub that extends behind the pivot toward `-x`, in + /// pixels. Set to `0` for a tip-only needle. + final double tailLength; + + /// Fill color of the needle. + final Color color; + + @override + void draw(Canvas canvas) { + final half = width / 2; + final path = Path() + ..moveTo(-tailLength, 0) + ..lineTo(0, -half) + ..lineTo(length, 0) + ..lineTo(0, half) + ..close(); + canvas.drawPath( + path, + Paint() + ..color = color + ..isAntiAlias = true, + ); + } + + @override + Size getSize() => Size(length + tailLength, width); + + @override + GaugePointerPainter lerp(GaugePointerPainter b, double t) { + if (b is! GaugePointerNeedlePainter) { + return b; + } + return GaugePointerNeedlePainter( + length: lerpDouble(length, b.length, t)!, + width: lerpDouble(width, b.width, t)!, + tailLength: lerpDouble(tailLength, b.tailLength, t)!, + color: Color.lerp(color, b.color, t)!, + ); + } + + @override + List get props => [length, width, tailLength, color]; +} + +/// [GaugePointerPainter] that draws a filled circle at +/// `(anchorRadius, 0)` in the pre-transformed frame. Useful for +/// marker-style pointers or as a pivot cap (set `anchorRadius: 0`) on +/// top of a needle. +class GaugePointerCirclePainter extends GaugePointerPainter { + const GaugePointerCirclePainter({ + this.radius = 6.0, + this.anchorRadius = 0.0, + this.color = const Color(0xFF000000), + this.strokeWidth = 0.0, + this.strokeColor = const Color(0xFF000000), + }) : assert(radius > 0, 'radius must be > 0'), + assert(anchorRadius >= 0, 'anchorRadius must be >= 0'), + assert(strokeWidth >= 0, 'strokeWidth must be >= 0'); + + /// Radius of the filled circle, in pixels. + final double radius; + + /// Distance from the gauge center to the circle's center, along the + /// radial direction (`+x` in the pre-transformed frame). + final double anchorRadius; + + /// Fill color of the circle. + final Color color; + + /// Width of an optional stroked outline. Zero (default) = no outline. + final double strokeWidth; + + /// Color of the optional stroked outline. + final Color strokeColor; + + @override + void draw(Canvas canvas) { + final centerPoint = Offset(anchorRadius, 0); + if (strokeWidth > 0 && strokeColor.a != 0) { + canvas.drawCircle( + centerPoint, + radius + strokeWidth / 2, + Paint() + ..color = strokeColor + ..style = PaintingStyle.stroke + ..strokeWidth = strokeWidth, + ); + } + canvas.drawCircle( + centerPoint, + radius, + Paint() + ..color = color + ..style = PaintingStyle.fill, + ); + } + + @override + Size getSize() { + final extent = radius + strokeWidth; + return Size(anchorRadius + extent, extent * 2); + } + + @override + GaugePointerPainter lerp(GaugePointerPainter b, double t) { + if (b is! GaugePointerCirclePainter) { + return b; + } + return GaugePointerCirclePainter( + radius: lerpDouble(radius, b.radius, t)!, + anchorRadius: lerpDouble(anchorRadius, b.anchorRadius, t)!, + color: Color.lerp(color, b.color, t)!, + strokeWidth: lerpDouble(strokeWidth, b.strokeWidth, t)!, + strokeColor: Color.lerp(strokeColor, b.strokeColor, t)!, + ); + } + + @override + List get props => + [radius, anchorRadius, color, strokeWidth, strokeColor]; +} + +class GaugeTouchData extends FlTouchData + with EquatableMixin { + GaugeTouchData({ + bool? enabled, + BaseTouchCallback? touchCallback, + MouseCursorResolver? mouseCursorResolver, + Duration? longPressDuration, + }) : super( + enabled ?? true, + touchCallback, + mouseCursorResolver, + longPressDuration, + ); + + @override + List get props => [ + enabled, + touchCallback, + mouseCursorResolver, + longPressDuration, + ]; +} + +/// Describes the state of a touch on a [GaugeChart]. +/// +/// A touch inside the arc's angular range always produces a +/// [GaugeTouchedRing] — even when it falls in the gap between rings +/// (`ringsSpace`) or outside every ring's radial band. In those +/// cases [touchedRing] is null and [touchedRingIndex] is -1, but +/// [touchValue] is still filled in. Touches entirely outside the +/// angular range produce null [GaugeTouchResponse.touchedRing]. +/// +/// When the hit ring is a [GaugeZonesRing], [touchedZone] and +/// [touchedZoneIndex] are populated with the specific band that +/// contains the touch angle. For a [GaugeProgressRing], [isOnValue] +/// tells you whether the touch sits on the filled portion (`touchValue +/// <= ring.value`) or the background. +@immutable +class GaugeTouchedRing with EquatableMixin { + const GaugeTouchedRing({ + required this.touchedRing, + required this.touchedRingIndex, + required this.touchAngle, + required this.touchRadius, + required this.touchValue, + required this.isOnValue, + this.touchedZone, + this.touchedZoneIndex = -1, + }); + + /// The ring that was touched, or null if the touch fell between / + /// outside rings. + final GaugeRing? touchedRing; + + /// Index of the touched ring in [GaugeChartData.rings], or -1 if + /// no ring was hit. + final int touchedRingIndex; + + /// Angle of the touch in degrees, using the same convention as + /// [GaugeChartData.startDegreeOffset] (0° points right). + final double touchAngle; + + /// Distance from the gauge's center to the touch, in pixels. + final double touchRadius; + + /// Touch position interpolated along the shared gauge scale, in + /// [[GaugeChartData.minValue], [GaugeChartData.maxValue]]. + final double touchValue; + + /// True when a [GaugeProgressRing] was hit AND the touch sits on + /// its filled portion (`touchValue <= ring.value`). False + /// otherwise, including for [GaugeZonesRing] hits and misses. + final bool isOnValue; + + /// The zone that was touched when the hit ring is a + /// [GaugeZonesRing] and the touch angle falls inside one of its + /// zones. Null for progress-ring hits and for touches in gaps + /// between zones. + final GaugeZone? touchedZone; + + /// Index of [touchedZone] in the hit ring's `zones` list, or -1. + final int touchedZoneIndex; + + @override + List get props => [ + touchedRing, + touchedRingIndex, + touchAngle, + touchRadius, + touchValue, + isOnValue, + touchedZone, + touchedZoneIndex, + ]; +} + +class GaugeTouchResponse extends BaseTouchResponse { + GaugeTouchResponse({ + required super.touchLocation, + required this.touchedRing, + }); + + /// Details of the touch, or null if the touch fell entirely outside + /// the arc's angular range. + final GaugeTouchedRing? touchedRing; + + GaugeTouchResponse copyWith({ + Offset? touchLocation, + GaugeTouchedRing? touchedRing, + }) => + GaugeTouchResponse( + touchLocation: touchLocation ?? this.touchLocation, + touchedRing: touchedRing ?? this.touchedRing, + ); +} diff --git a/lib/src/chart/gauge_chart/gauge_chart_painter.dart b/lib/src/chart/gauge_chart/gauge_chart_painter.dart new file mode 100644 index 000000000..68df06ee1 --- /dev/null +++ b/lib/src/chart/gauge_chart/gauge_chart_painter.dart @@ -0,0 +1,507 @@ +import 'dart:math' as math; + +import 'package:fl_chart/fl_chart.dart'; +import 'package:fl_chart/src/chart/base/base_chart/base_chart_painter.dart'; +import 'package:fl_chart/src/utils/canvas_wrapper.dart'; +import 'package:fl_chart/src/utils/utils.dart'; +import 'package:flutter/material.dart'; + +class GaugeChartPainter extends BaseChartPainter { + GaugeChartPainter() : super() { + _arcPaint = Paint()..isAntiAlias = true; + } + + late Paint _arcPaint; + + @visibleForTesting + Offset center(Size size) => Offset(size.width / 2.0, size.height / 2.0); + + @override + void paint( + BuildContext context, + CanvasWrapper canvasWrapper, + PaintHolder holder, + ) { + super.paint(context, canvasWrapper, holder); + drawSections(canvasWrapper, holder); + drawTicks(context, canvasWrapper, holder); + drawPointers(canvasWrapper, holder); + } + + /// Draws every ring. Dispatches on the concrete [GaugeRing] type + /// so progress rings (`GaugeProgressRing`) and zones rings + /// (`GaugeZonesRing`) paint with their own logic. + @visibleForTesting + void drawSections( + CanvasWrapper canvasWrapper, + PaintHolder holder, + ) { + final data = holder.data; + final strokeCenters = _sectionStrokeCenters(canvasWrapper.size, data); + for (var i = 0; i < data.rings.length; i++) { + final ring = data.rings[i]; + final width = data.resolveRingWidth(ring); + final radius = strokeCenters[i]; + final rect = + Rect.fromCircle(center: center(canvasWrapper.size), radius: radius); + + switch (ring) { + case GaugeProgressRing(): + _drawProgressSection(canvasWrapper, data, ring, rect, width); + case GaugeZonesRing(): + _drawZonesSection(canvasWrapper, data, ring, rect, width, radius); + } + } + } + + void _drawProgressSection( + CanvasWrapper canvasWrapper, + GaugeChartData data, + GaugeProgressRing ring, + Rect rect, + double width, + ) { + final signedSweep = _signedSweep(data); + final range = data.maxValue - data.minValue; + + if (ring.backgroundColor != null) { + _arcPaint + ..color = ring.backgroundColor! + ..strokeWidth = width + ..strokeCap = ring.strokeCap + ..style = PaintingStyle.stroke; + canvasWrapper.drawArc( + rect, + Utils().radians(data.startDegreeOffset), + Utils().radians(signedSweep), + false, + _arcPaint, + ); + } + + final filledSweep = signedSweep * ((ring.value - data.minValue) / range); + _arcPaint + ..color = ring.color + ..strokeWidth = width + ..strokeCap = ring.strokeCap + ..style = PaintingStyle.stroke; + canvasWrapper.drawArc( + rect, + Utils().radians(data.startDegreeOffset), + Utils().radians(filledSweep), + false, + _arcPaint, + ); + } + + void _drawZonesSection( + CanvasWrapper canvasWrapper, + GaugeChartData data, + GaugeZonesRing ring, + Rect rect, + double width, + double strokeCenterRadius, + ) { + final dir = data.direction == GaugeDirection.clockwise ? 1 : -1; + final degreesPerUnit = data.sweepAngle / (data.maxValue - data.minValue); + + void drawZoneArc(GaugeZone zone) { + final startDeg = data.startDegreeOffset + + dir * (zone.from - data.minValue) * degreesPerUnit; + final sweepDeg = dir * (zone.to - zone.from) * degreesPerUnit; + _arcPaint + ..color = zone.color + ..strokeWidth = width + ..strokeCap = zone.strokeCap + ..style = PaintingStyle.stroke + ..blendMode = BlendMode.srcOver; + canvasWrapper.drawArc( + rect, + Utils().radians(startDeg), + Utils().radians(sweepDeg), + false, + _arcPaint, + ); + } + + // No spacing needed — draw each zone full-angular. + if (ring.zonesSpace == 0 || ring.zones.length < 2) { + ring.zones.forEach(drawZoneArc); + return; + } + + // Draw each zone full-angular, then carve a perpendicular + // rectangular strip at each internal boundary. The strip has a + // constant perpendicular width of `zonesSpace`, so the visible gap + // stays uniform across the ring's thickness (no wedge effect). + // `saveLayer` + `BlendMode.clear` is the standard technique for + // erasing already-painted pixels without leaking to the background. + final c = center(canvasWrapper.size); + final layerBounds = Rect.fromCircle( + center: c, + radius: strokeCenterRadius + width, + ); + canvasWrapper.saveLayer(layerBounds, Paint()); + ring.zones.forEach(drawZoneArc); + final clearPaint = Paint() + ..blendMode = BlendMode.clear + ..style = PaintingStyle.fill + ..isAntiAlias = true; + final capRadius = width / 2; + // Half-gap angular offset: the tangent distance from the boundary + // to each zone's new stroke-center edge is `zonesSpace / 2`. At + // stroke-center radius, that maps to this angle. + final halfGapAngleRad = (ring.zonesSpace / 2) / strokeCenterRadius; + for (var i = 0; i < ring.zones.length - 1; i++) { + final boundaryDeg = data.startDegreeOffset + + dir * (ring.zones[i].to - data.minValue) * degreesPerUnit; + final boundaryRad = Utils().radians(boundaryDeg); + final strip = _perpendicularStripPath( + center: c, + angleRad: boundaryRad, + strokeCenterRadius: strokeCenterRadius, + strokeWidth: width, + zonesSpace: ring.zonesSpace, + ); + canvasWrapper.drawPath(strip, clearPaint); + + // Re-add rounded caps on each side of the gap for zones that + // opted into StrokeCap.round. The full-angular arc drew the + // caps at the *original* boundary, which the strip just erased; + // we paint them back at each zone's shrunk end so the pill + // aesthetic survives without widening the visible gap beyond + // `zonesSpace - strokeWidth`. + final zoneBefore = ring.zones[i]; + if (zoneBefore.strokeCap == StrokeCap.round) { + final capAngle = boundaryRad - dir * halfGapAngleRad; + canvasWrapper.drawCircle( + Offset( + c.dx + strokeCenterRadius * math.cos(capAngle), + c.dy + strokeCenterRadius * math.sin(capAngle), + ), + capRadius, + Paint() + ..color = zoneBefore.color + ..isAntiAlias = true, + ); + } + final zoneAfter = ring.zones[i + 1]; + if (zoneAfter.strokeCap == StrokeCap.round) { + final capAngle = boundaryRad + dir * halfGapAngleRad; + canvasWrapper.drawCircle( + Offset( + c.dx + strokeCenterRadius * math.cos(capAngle), + c.dy + strokeCenterRadius * math.sin(capAngle), + ), + capRadius, + Paint() + ..color = zoneAfter.color + ..isAntiAlias = true, + ); + } + } + canvasWrapper.restore(); + } + + /// Builds a rectangular path centered on the radial line at + /// [angleRad], perpendicular to it, used to carve a uniform-width + /// gap between two adjacent zones. + /// + /// - Perpendicular extent (across the gap): [zonesSpace]. + /// - Radial extent (along the ring): `strokeWidth * 2`, centered on + /// [strokeCenterRadius] so the strip fully clears the ring plus + /// any round/square caps on the adjacent zones. + Path _perpendicularStripPath({ + required Offset center, + required double angleRad, + required double strokeCenterRadius, + required double strokeWidth, + required double zonesSpace, + }) { + final cosA = math.cos(angleRad); + final sinA = math.sin(angleRad); + // Tangent unit vector = radial rotated 90° CCW. + final tx = -sinA; + final ty = cosA; + final half = zonesSpace / 2; + final rOuter = strokeCenterRadius + strokeWidth; + final rInner = math.max(0, strokeCenterRadius - strokeWidth); + Offset corner(double r, double s) => Offset( + center.dx + cosA * r + tx * half * s, + center.dy + sinA * r + ty * half * s, + ); + final p1 = corner(rOuter, 1); + final p2 = corner(rOuter, -1); + final p3 = corner(rInner, -1); + final p4 = corner(rInner, 1); + return Path() + ..moveTo(p1.dx, p1.dy) + ..lineTo(p2.dx, p2.dy) + ..lineTo(p3.dx, p3.dy) + ..lineTo(p4.dx, p4.dy) + ..close(); + } + + /// Returns a [GaugeTouchedRing] describing what the touch hit, or + /// null when the touch was entirely outside the gauge's angular range. + /// + /// When the touch is on-arc but falls in the gap between rings (or + /// outside every ring's radial band) the returned ring has + /// [GaugeTouchedRing.touchedRingIndex] == -1 while still carrying + /// a valid [GaugeTouchedRing.touchValue]. + GaugeTouchedRing? handleTouch( + Offset touchedPoint, + Size viewSize, + PaintHolder holder, + ) { + final data = holder.data; + final c = center(viewSize); + final vector = touchedPoint - c; + final distance = vector.distance; + final touchAngleDeg = Utils().degrees(vector.direction); + + final along = _angleAlongSweep(touchAngleDeg, data); + if (along == null) return null; + + final range = data.maxValue - data.minValue; + final touchValue = data.minValue + (along / data.sweepAngle) * range; + + final strokeCenters = _sectionStrokeCenters(viewSize, data); + for (var i = 0; i < data.rings.length; i++) { + final ring = data.rings[i]; + final width = data.resolveRingWidth(ring); + final threshold = data.ringsSpace / 2; + if ((distance - strokeCenters[i]).abs() > width / 2 + threshold) continue; + + switch (ring) { + case GaugeProgressRing(): + return GaugeTouchedRing( + touchedRing: ring, + touchedRingIndex: i, + touchAngle: touchAngleDeg, + touchRadius: distance, + touchValue: touchValue, + isOnValue: touchValue <= ring.value, + ); + case GaugeZonesRing(): + var zoneIndex = -1; + GaugeZone? zone; + for (var j = 0; j < ring.zones.length; j++) { + final z = ring.zones[j]; + if (touchValue >= z.from && touchValue <= z.to) { + zoneIndex = j; + zone = z; + // Later zones paint on top in drawZonesSection, so the + // visually-topmost zone is the last match — keep iterating. + } + } + return GaugeTouchedRing( + touchedRing: ring, + touchedRingIndex: i, + touchAngle: touchAngleDeg, + touchRadius: distance, + touchValue: touchValue, + isOnValue: false, + touchedZone: zone, + touchedZoneIndex: zoneIndex, + ); + } + } + + return GaugeTouchedRing( + touchedRing: null, + touchedRingIndex: -1, + touchAngle: touchAngleDeg, + touchRadius: distance, + touchValue: touchValue, + isOnValue: false, + ); + } + + /// Padding reserved past the widget's shortest side for + /// outer-positioned ticks (and their labels, when present). + /// + /// Accounts for the tick's radial extent (`painter.getSize().width` + /// because the canvas is rotated so `+x` is radial), the signed + /// [GaugeTicks.offset], and — when [GaugeTicks.labelBuilder] is set + /// — a label-height heuristic (`labelStyle.fontSize * 1.2`, falling + /// back to 14) plus [GaugeTicks.labelOffset]. + double _outerTickPadding(GaugeChartData data) { + final ticks = data.ticks; + if (ticks == null || ticks.position != GaugeTickPosition.outer) return 0; + var padding = ticks.offset + ticks.painter.getSize().width; + if (ticks.labelBuilder != null) { + final labelHeight = (ticks.labelStyle?.fontSize ?? 14) * 1.2; + padding += ticks.labelOffset + labelHeight; + } + return math.max(0, padding); + } + + /// Outer radius available for the gauge's rings — shrunk by + /// [_outerTickPadding] when outer ticks are configured. + double _outerArcRadius(Size viewSize, GaugeChartData data) => + viewSize.shortestSide / 2 - _outerTickPadding(data); + + /// Total radial thickness consumed by all rings plus the gaps between + /// them. + double _totalRingsDepth(GaugeChartData data) { + var depth = data.ringsSpace * (data.rings.length - 1); + for (final ring in data.rings) { + depth += data.resolveRingWidth(ring); + } + return depth; + } + + /// Stroke-centered radius per ring, indexed to match + /// [GaugeChartData.rings]: entry 0 is the innermost ring, the last + /// entry is the outermost. + List _sectionStrokeCenters(Size viewSize, GaugeChartData data) { + final outer = _outerArcRadius(viewSize, data); + final innerEdge = outer - _totalRingsDepth(data); + final centers = []; + var currentInner = innerEdge; + for (var i = 0; i < data.rings.length; i++) { + if (i > 0) currentInner += data.ringsSpace; + final width = data.resolveRingWidth(data.rings[i]); + centers.add(currentInner + width / 2); + currentInner += width; + } + return centers; + } + + /// Radial position of the tick's anchor point (where the canvas + /// origin sits before the painter's `draw()` is called). + double _tickAnchorRadius(Size viewSize, GaugeChartData data) { + final ticks = data.ticks!; + final outer = _outerArcRadius(viewSize, data); + final inner = outer - _totalRingsDepth(data); + return switch (ticks.position) { + GaugeTickPosition.outer => outer + ticks.offset, + GaugeTickPosition.inner => inner - ticks.offset, + GaugeTickPosition.center => (outer + inner) / 2 + ticks.offset, + }; + } + + /// Draws every tick + optional label. The canvas is saved / + /// translated / rotated around each tick anchor so the painter can + /// draw a horizontal right-facing shape at the origin. Labels are + /// rendered upright (no rotation) past the tick's far edge. + @visibleForTesting + void drawTicks( + BuildContext context, + CanvasWrapper canvasWrapper, + PaintHolder holder, + ) { + final data = holder.data; + final ticks = data.ticks; + if (ticks == null) return; + + final viewSize = canvasWrapper.size; + final c = center(viewSize); + final dir = data.direction == GaugeDirection.clockwise ? 1 : -1; + final tickAnchorRadius = _tickAnchorRadius(viewSize, data); + final outwardSign = ticks.position == GaugeTickPosition.inner ? -1.0 : 1.0; + final rotationOffset = + ticks.position == GaugeTickPosition.inner ? math.pi : 0.0; + final tickFarRadius = + tickAnchorRadius + outwardSign * ticks.painter.getSize().width; + final interTickDegrees = (dir * data.sweepAngle) / (ticks.count - 1); + final labelStyle = ticks.labelBuilder != null + ? Utils().getThemeAwareTextStyle(context, ticks.labelStyle) + : null; + final range = data.maxValue - data.minValue; + + final lastIndex = ticks.count - 1; + for (var i = 0; i < ticks.count; i++) { + final progress = i / lastIndex; + final value = data.minValue + progress * range; + final tickInfo = GaugeTickInfo( + index: i, + count: ticks.count, + value: value, + minValue: data.minValue, + maxValue: data.maxValue, + ); + final shouldShow = ticks.checkToShowTick(tickInfo); + if (!shouldShow) continue; + final angleRad = + Utils().radians(data.startDegreeOffset + interTickDegrees * i); + final anchor = Offset( + c.dx + tickAnchorRadius * math.cos(angleRad), + c.dy + tickAnchorRadius * math.sin(angleRad), + ); + + canvasWrapper + ..save() + ..translate(anchor.dx, anchor.dy) + ..rotate(angleRad + rotationOffset); + ticks.painter.draw(canvasWrapper.canvas, tickInfo); + canvasWrapper.restore(); + + if (labelStyle != null) { + final text = ticks.labelBuilder!(value); + final tp = TextPainter( + text: TextSpan(text: text, style: labelStyle), + textDirection: TextDirection.ltr, + textScaler: holder.textScaler, + )..layout(); + final labelCenterRadius = + tickFarRadius + outwardSign * (ticks.labelOffset + tp.height / 2); + final labelCenter = Offset( + c.dx + labelCenterRadius * math.cos(angleRad), + c.dy + labelCenterRadius * math.sin(angleRad), + ); + canvasWrapper.drawText( + tp, + Offset(labelCenter.dx - tp.width / 2, labelCenter.dy - tp.height / 2), + ); + } + } + } + + double _signedSweep(GaugeChartData data) => + data.direction == GaugeDirection.clockwise + ? data.sweepAngle + : -data.sweepAngle; + + /// Draws every [GaugePointer] on top of the rings and ticks. Each + /// pointer's canvas is pre-translated to the gauge center and + /// pre-rotated so `+x` points radially toward the pointer's value + /// angle — see [GaugePointerPainter.draw] for the local frame. + @visibleForTesting + void drawPointers( + CanvasWrapper canvasWrapper, + PaintHolder holder, + ) { + final data = holder.data; + if (data.pointers.isEmpty) return; + + final c = center(canvasWrapper.size); + final dir = data.direction == GaugeDirection.clockwise ? 1 : -1; + final range = data.maxValue - data.minValue; + + for (final pointer in data.pointers) { + final progress = (pointer.value - data.minValue) / range; + final angleRad = Utils().radians( + data.startDegreeOffset + dir * data.sweepAngle * progress, + ); + canvasWrapper + ..save() + ..translate(c.dx, c.dy) + ..rotate(angleRad); + pointer.painter.draw(canvasWrapper.canvas); + canvasWrapper.restore(); + } + } + + /// Projects [touchDeg] onto the arc's local angular coordinate + /// (0 at start, positive toward sweep end). Returns null when the + /// touch is outside the angular range. + double? _angleAlongSweep(double touchDeg, GaugeChartData data) { + final dir = data.direction == GaugeDirection.clockwise ? 1 : -1; + var rel = dir * (touchDeg - data.startDegreeOffset); + rel = ((rel % 360) + 360) % 360; + if (rel <= data.sweepAngle) return rel; + return null; + } +} diff --git a/lib/src/chart/gauge_chart/gauge_chart_renderer.dart b/lib/src/chart/gauge_chart/gauge_chart_renderer.dart new file mode 100644 index 000000000..d003486a5 --- /dev/null +++ b/lib/src/chart/gauge_chart/gauge_chart_renderer.dart @@ -0,0 +1,116 @@ +import 'package:fl_chart/src/chart/base/base_chart/base_chart_painter.dart'; +import 'package:fl_chart/src/chart/base/base_chart/render_base_chart.dart'; +import 'package:fl_chart/src/chart/gauge_chart/gauge_chart_data.dart'; +import 'package:fl_chart/src/chart/gauge_chart/gauge_chart_painter.dart'; +import 'package:fl_chart/src/utils/canvas_wrapper.dart'; +import 'package:flutter/widgets.dart'; + +// coverage:ignore-start + +/// Low level GaugeChart Widget. +class GaugeChartLeaf extends LeafRenderObjectWidget { + const GaugeChartLeaf({ + super.key, + required this.data, + required this.targetData, + }); + + final GaugeChartData data; + final GaugeChartData targetData; + + @override + RenderGaugeChart createRenderObject(BuildContext context) => RenderGaugeChart( + context, + data, + targetData, + MediaQuery.of(context).textScaler, + ); + + @override + void updateRenderObject(BuildContext context, RenderGaugeChart renderObject) { + renderObject + ..data = data + ..targetData = targetData + ..textScaler = MediaQuery.of(context).textScaler + ..buildContext = context; + } +} +// coverage:ignore-end + +/// Renders our GaugeChart, also handles hitTest. +class RenderGaugeChart extends RenderBaseChart { + RenderGaugeChart( + BuildContext context, + GaugeChartData data, + GaugeChartData targetData, + TextScaler textScaler, + ) : _data = data, + _targetData = targetData, + _textScaler = textScaler, + super(targetData.gaugeTouchData, context, canBeScaled: false); + + GaugeChartData _data; + GaugeChartData _targetData; + + TextScaler _textScaler; + + // We couldn't mock [size] property of this class, that's why we have this + @visibleForTesting + Size? mockTestSize; + @visibleForTesting + GaugeChartPainter painter = GaugeChartPainter(); + + GaugeChartData get data => _data; + + set data(GaugeChartData value) { + if (_data == value) return; + _data = value; + markNeedsPaint(); + } + + PaintHolder get paintHolder { + return PaintHolder(data, targetData, textScaler); + } + + GaugeChartData get targetData => _targetData; + + set targetData(GaugeChartData value) { + if (_targetData == value) return; + _targetData = value; + super.updateBaseTouchData(_targetData.gaugeTouchData); + markNeedsPaint(); + } + + TextScaler get textScaler => _textScaler; + + set textScaler(TextScaler value) { + if (_textScaler == value) return; + _textScaler = value; + markNeedsPaint(); + } + + @override + GaugeTouchResponse getResponseAtLocation(Offset localPosition) { + return GaugeTouchResponse( + touchLocation: localPosition, + touchedRing: painter.handleTouch( + localPosition, + mockTestSize ?? size, + paintHolder, + ), + ); + } + + @override + void paint(PaintingContext context, Offset offset) { + final canvas = context.canvas + ..save() + ..translate(offset.dx, offset.dy); + painter.paint( + buildContext, + CanvasWrapper(canvas, mockTestSize ?? size), + paintHolder, + ); + canvas.restore(); + } +} diff --git a/lib/src/utils/lerp.dart b/lib/src/utils/lerp.dart index b79bfee3a..7958910e6 100644 --- a/lib/src/utils/lerp.dart +++ b/lib/src/utils/lerp.dart @@ -143,6 +143,30 @@ List? lerpPieChartStackSegmentDataList( ) => lerpList(a, b, t, lerp: PieChartStackSegmentData.lerp); +/// Lerps [GaugeRing] list based on [t] value, check [Tween.lerp]. +List? lerpGaugeRingList( + List? a, + List? b, + double t, +) => + lerpList(a, b, t, lerp: GaugeRing.lerp); + +/// Lerps [GaugeZone] list based on [t] value, check [Tween.lerp]. +List? lerpGaugeZoneList( + List? a, + List? b, + double t, +) => + lerpList(a, b, t, lerp: GaugeZone.lerp); + +/// Lerps [GaugePointer] list based on [t] value, check [Tween.lerp]. +List? lerpGaugePointerList( + List? a, + List? b, + double t, +) => + lerpList(a, b, t, lerp: GaugePointer.lerp); + /// Lerps [ScatterSpot] list based on [t] value, check [Tween.lerp]. List? lerpScatterSpotList( List? a, diff --git a/repo_files/documentations/gauge_chart.md b/repo_files/documentations/gauge_chart.md new file mode 100644 index 000000000..e782d4c16 --- /dev/null +++ b/repo_files/documentations/gauge_chart.md @@ -0,0 +1,271 @@ +### How to use +```dart +GaugeChart( + GaugeChartData( + // read about it in the GaugeChartData ring + ), + duration: Duration(milliseconds: 150), // Optional + curve: Curves.linear, // Optional +); +``` + +A gauge is drawn as a set of **concentric rings** along a shared arc. All rings share the same `minValue`/`maxValue` scale and stack **innermost-first** in list order — so `rings[0]` is the innermost ring, the last entry is the outermost — with an optional `ringsSpace` radial gap between them. + +Each ring is one of two shapes: + +- **[GaugeProgressRing](#GaugeProgressRing)** — a ring that fills from `minValue` up to its own `value`, with an optional faded `backgroundColor` behind. Use this for measurements (battery level, goal progress, live reading). +- **[GaugeZonesRing](#GaugeZonesRing)** — a ring divided into fixed colored [GaugeZone](#GaugeZone) bands. Use this for threshold/level indicators (speedometer red-amber-green zones, status bands). + +You can mix both kinds freely — a common pattern is an inner progress ring showing the current reading plus an outer zones ring showing threshold bands. + +### Implicit Animations +When you change the chart's state, it animates to the new state internally (using [implicit animations](https://flutter.dev/docs/development/ui/animations/implicit-animations)). You can control the animation [duration](https://api.flutter.dev/flutter/dart-core/Duration-class.html) and [curve](https://api.flutter.dev/flutter/animation/Curves-class.html) using optional `duration` and `curve` properties. Lerping a ring to a different shape (`GaugeProgressRing` ↔ `GaugeZonesRing`) snaps to the target — same-shape transitions interpolate smoothly. + +### Progress gauge shortcut +For the common "single ring filling from 0 to a value" case, use `GaugeChartData.progress`: + +```dart +GaugeChart( + GaugeChartData.progress( + value: 0.73, + color: Colors.blue, + width: 30, + backgroundColor: Colors.black12, + // defaults: min=0, max=1, startDegreeOffset=-225, sweepAngle=270 + ), +); +``` + +### Multi-ring ("Apple Watch") gauge + +```dart +GaugeChart( + GaugeChartData( + minValue: 0, + maxValue: 100, + startDegreeOffset: -225, + sweepAngle: 270, + defaultRingWidth: 22, + ringsSpace: 4, + rings: [ + // innermost + GaugeProgressRing( + value: 72, + color: Colors.red, + backgroundColor: Colors.red.withValues(alpha: 0.2), + ), + GaugeProgressRing( + value: 48, + color: Colors.green, + backgroundColor: Colors.green.withValues(alpha: 0.2), + ), + // outermost + GaugeProgressRing( + value: 90, + color: Colors.blue, + backgroundColor: Colors.blue.withValues(alpha: 0.2), + ), + ], + ), +); +``` + +### Speedometer with threshold zones + +```dart +GaugeChart( + GaugeChartData( + minValue: 350, + maxValue: 850, + startDegreeOffset: 180, + sweepAngle: 180, + ringsSpace: 4, + rings: [ + // inner ring — current measurement + GaugeProgressRing( + value: 370, + color: Colors.green, + backgroundColor: Colors.grey, + width: 30, + ), + // outer ring — colored threshold bands, with a visible pixel + // gap between neighbors + GaugeZonesRing( + width: 10, + zonesSpace: 4, + zones: [ + GaugeZone(from: 350, to: 600, color: Colors.redAccent), + GaugeZone(from: 600, to: 700, color: Colors.amber), + GaugeZone(from: 700, to: 800, color: Colors.lightGreen), + GaugeZone(from: 800, to: 850, color: Colors.green), + ], + ), + ], + ), +); +``` + +### GaugeChartData +|PropName|Description|default value| +|:-------|:----------|:------------| +|rings| list of [GaugeRing](#GaugeRing) rings, innermost first. All rings share the same `minValue`/`maxValue` scale|required| +|minValue| lower bound of the gauge scale (inclusive), shared by every ring|0.0| +|maxValue| upper bound of the gauge scale (inclusive), shared by every ring|1.0| +|startDegreeOffset| starting angle of the arc, in degrees. `0°` points right, same convention as [PieChartData.startDegreeOffset](pie_chart.md#PieChartData)|-225.0| +|sweepAngle| length of the arc in degrees, must be in `(0, 360]`|270.0| +|direction| whether the arc travels clockwise or counter-clockwise from `startDegreeOffset` — see [GaugeDirection](#GaugeDirection)|GaugeDirection.clockwise| +|defaultRingWidth| width used for rings that don't specify their own `width`|10.0| +|ringsSpace| radial pixel gap between adjacent rings|0.0| +|ticks| optional tick configuration; see [GaugeTicks](#GaugeTicks)|null| +|pointers| list of [GaugePointer](#GaugePointer)s drawn on top of the rings and ticks. Empty by default; each pointer carries its own `value` on the shared scale|`[]`| +|touchData| [GaugeTouchData](#GaugeTouchData) holds the touch interactivity details|GaugeTouchData()| +|borderData| shows a border around the chart, see [FlBorderData](base_chart.md#FlBorderData)|FlBorderData()| + +### GaugeRing +`GaugeRing` is a sealed base type — every ring is one of the two concrete shapes below. You can pattern-match on the concrete type in touch callbacks. All rings share: + +|PropName|Description|default value| +|:-------|:----------|:------------| +|width| stroke width in pixels. If null, `GaugeChartData.defaultRingWidth` is used|null| + +### GaugeProgressRing +A ring filled from `GaugeChartData.minValue` up to `value`. The unfilled portion (`value..maxValue`) is painted in `backgroundColor` when provided. Its two arcs (background + filled) share one `strokeCap`. + +|PropName|Description|default value| +|:-------|:----------|:------------| +|value| current progress on the gauge scale|required| +|color| stroke color of the filled portion|required| +|backgroundColor| optional stroke color for the unfilled portion. If null, no background is drawn|null| +|strokeCap| cap style for both the background and filled arcs of this ring. Use `StrokeCap.round` for a rounded "tip" where the value ends|StrokeCap.butt| +|width| inherited from [GaugeRing](#GaugeRing)|null| + +### GaugeZonesRing +A ring divided into fixed colored [GaugeZone](#GaugeZone) bands. Zones are bounds-checked against the chart's `minValue`/`maxValue` but are not required to be sorted, contiguous, or non-overlapping — they're drawn in list order, so later zones paint on top of overlapping earlier ones. Cap style is configured **per zone** via [GaugeZone.strokeCap](#GaugeZone), not at the ring level. + +|PropName|Description|default value| +|:-------|:----------|:------------| +|zones| list of [GaugeZone](#GaugeZone) bands painted along this ring's arc|required| +|zonesSpace| visible gap between adjacent zones, in pixels, measured **perpendicular to the ring** — so the gap has the same width at the ring's inner and outer edges regardless of how thick the ring is. Applied **only between zones** (in list order) by carving a rectangular strip at each internal boundary. The first zone's leading edge and the last zone's trailing edge are left flush to the gauge's angular extremes. Per-zone `StrokeCap.round` is preserved: rounded neighbors keep a pill look across the gap (effective visible gap = `zonesSpace − width`), so set `zonesSpace > width` to keep a visible separator when caps are rounded.|0.0| +|width| inherited from [GaugeRing](#GaugeRing)|null| + +### GaugeZone +A single colored band within a [GaugeZonesRing](#GaugeZonesRing). + +|PropName|Description|default value| +|:-------|:----------|:------------| +|from| lower bound of the zone on the gauge scale (inclusive)|required| +|to| upper bound of the zone on the gauge scale (inclusive); must be `>= from`|required| +|color| fill color of this band|required| +|strokeCap| cap style for this band's two ends. Adjacent zones paint in list order, so a later zone's `butt` start paints over an earlier zone's rounded end-cap bulge — useful for getting rounded outer extremes with clean internal boundaries|StrokeCap.butt| + +### GaugeDirection +|Value|Behavior| +|:----|:-------| +|`clockwise`| arc travels clockwise from `startDegreeOffset`.| +|`counterClockwise`| arc travels counter-clockwise from `startDegreeOffset`.| + +### GaugeTicks +Tick marks drawn along the gauge's scale. Ticks frame the gauge as a whole — they reference the ring stack's outer edge, inner edge, or radial center — and are not owned by any individual ring. Ticks are evenly spaced from `startDegreeOffset` across the sweep (endpoints included). + +|PropName|Description|default value| +|:-------|:----------|:------------| +|count| number of ticks drawn, including both sweep endpoints; must be `>= 2`|3| +|position| where ticks sit — see [GaugeTickPosition](#GaugeTickPosition)|GaugeTickPosition.outer| +|offset| **signed** pixel delta from the natural tick anchor, measured along the `position`'s outward axis (away from center for `outer`, toward center for `inner`, toward outer for `center`). Positive extends the tick farther in that direction; negative pulls it back toward / across the ring stack.|0| +|painter| [GaugeTickPainter](#GaugeTickPainter) that renders each tick|GaugeTickLinePainter()| +|CheckToShowGaugeTick| `bool Function(CheckToShowGaugeTickInfo info)` — predicate called per tick. Returning `false` skips both the tick mark and its label. Receives the tick's `index`, the total `count`, its scale `value`, and the chart's `minValue` / `maxValue`. Two predefined predicates ship on `GaugeTicks`: `GaugeTicks.showAll` (the default) and `GaugeTicks.hideEndpoints` (skip the first and last tick — handy when the arc already visually anchors its extremes via rounded zone caps). Use top-level / static references rather than anonymous closures so equality holds across rebuilds.|GaugeTicks.showAll| +|labelBuilder| optional `String Function(double value)` returning the label for each tick's scale value. `null` means no labels.|null| +|labelStyle| style applied to labels, merged with the current theme via `getThemeAwareTextStyle`. `null` inherits the theme's default text style.|null| +|labelOffset| **signed** pixel delta between the tick's far edge and the label center, along the same outward axis as `offset`. Positive pushes the label further outward; negative pulls it toward / across the tick.|0| + +### GaugeTickPosition +|Value|Behavior| +|:----|:-------| +|`outer`| ticks sit outside the outermost ring; reserves radial padding so the ring stack fits inside the widget bounds.| +|`inner`| ticks sit inside the innermost ring's inner edge, toward the gauge center.| +|`center`| ticks are radially centered between the outermost and innermost ring edges.| + +### GaugeTickPainter +Interface for rendering a single tick mark. Subclass it to draw custom tick shapes. Mirrors the [FlDotPainter](line_chart.md) pattern. + +**Pre-transformed canvas** — the gauge painter translates and rotates the canvas around each tick's anchor before calling `draw`, so implementations never touch trigonometry: + +- origin `(0, 0)` is the tick's anchor on the gauge +- `+x` axis points in the tick's outward direction (per `GaugeTicks.position`) +- `+y` axis is tangent to the arc in the sweep direction + +Draw a horizontal, right-facing shape at the origin; the gauge handles placing and rotating it for every tick angle. `getSize()` reports the bounding box in this unrotated local frame — `width` is the radial extent (used for outer padding), `height` is the tangential extent. + +Built-in implementations: +- **GaugeTickLinePainter** — draws a line from the origin to `(length, 0)`; the canonical tick shape. Properties: `length` (default 6), `thickness` (default 2), `color` (default black). This is the default. +- **GaugeTickCirclePainter** — rotation-invariant filled circle, optionally with a stroked outline. Properties: `radius` (default 3), `color` (default black), `strokeWidth` (default 0), `strokeColor` (default black). + +### GaugePointer +A single pointer rendered on top of the rings and ticks, indicating a value on the gauge's scale. Each pointer carries its own `value` — independent from any ring — so you can stack multiple pointers (clock hands, dual readings, a needle plus a pivot cap) by adding more entries to `GaugeChartData.pointers`. + +|PropName|Description|default value| +|:-------|:----------|:------------| +|value| position on the gauge scale the pointer points at. Values outside `[minValue, maxValue]` simply extend past the sweep endpoints|required| +|painter| [GaugePointerPainter](#GaugePointerPainter) that renders the pointer's shape|GaugePointerNeedlePainter()| + +### GaugePointerPainter +Interface for rendering a single [GaugePointer](#GaugePointer). Subclass it to draw custom pointer shapes. Mirrors the [GaugeTickPainter](#GaugeTickPainter) pattern. + +**Pre-transformed canvas** — the gauge painter translates and rotates the canvas around the gauge's center before calling `draw`, so implementations never touch trigonometry: + +- origin `(0, 0)` is the **gauge center** +- `+x` axis points **radially outward** toward the pointer's value angle +- `+y` axis is **tangent** to the arc in the sweep direction + +Draw a horizontal, right-facing shape at the origin; the gauge rotates and translates the canvas for every pointer's value. `getSize()` reports the bounding box in this unrotated local frame — `width` is the radial extent, `height` is the tangential extent. + +Built-in implementations: +- **GaugePointerNeedlePainter** — classic triangular needle anchored at the gauge center, tapering to a point at `(length, 0)`. Properties: `length` (default 60), `width` (default 8), `tailLength` (default 0 — optional stub behind the pivot), `color` (default black). This is the default. +- **GaugePointerCirclePainter** — filled circle at `(anchorRadius, 0)`. Useful for marker-style pointers or as a pivot cap (`anchorRadius: 0`). Properties: `radius` (default 6), `anchorRadius` (default 0), `color` (default black), `strokeWidth` (default 0), `strokeColor` (default black). + +A classic speedometer needle with a pivot cap is just two pointers with the same value: + +```dart +pointers: const [ + GaugePointer( + value: 0.65, + painter: GaugePointerNeedlePainter(length: 70, width: 8, tailLength: 14), + ), + GaugePointer( + value: 0.65, + painter: GaugePointerCirclePainter(radius: 8, color: Colors.black), + ), +], +``` + +### GaugeTouchData ([read about touch handling](handle_touches.md)) +|PropName|Description|default value| +|:-------|:----------|:------------| +|enabled|determines whether to enable or disable touch behaviors|true| +|mouseCursorResolver|you can change the mouse cursor based on the provided [FlTouchEvent](base_chart.md#fltouchevent) and [GaugeTouchResponse](#GaugeTouchResponse)|MouseCursor.defer| +|touchCallback| listen to this callback to retrieve touch/pointer events and responses|null| +|longPressDuration| allows you to customize the duration of the longPress gesture. If null, the duration is [kLongPressTimeout](https://api.flutter.dev/flutter/gestures/kLongPressTimeout-constant.html)|null| + +### GaugeTouchResponse +|PropName|Description|default value| +|:-------|:----------|:------------| +|touchLocation|the location of the touch event in device pixel coordinates|required| +|touchedRing|Instance of [GaugeTouchedRing](#GaugeTouchedRing) describing what the touch hit, or null when the touch fell entirely outside the arc's angular range|null| + +### GaugeTouchedRing +A touch inside the arc's angular range always produces a `GaugeTouchedRing` — even when it falls in the gap between rings (`ringsSpace`) or outside every ring's radial band. In those cases `touchedRing` is null and `touchedRingIndex` is `-1`, but `touchValue` is still filled in. + +When the hit ring is a [GaugeProgressRing](#GaugeProgressRing), `isOnValue` is `true` if the touch sits on the filled portion (`touchValue <= ring.value`). + +When the hit ring is a [GaugeZonesRing](#GaugeZonesRing), `touchedZone` / `touchedZoneIndex` report the specific band the touch angle falls into (or null when it's in a gap between zones). + +|PropName|Description|default value| +|:-------|:----------|:------------| +|touchedRing|the [GaugeRing](#GaugeRing) (ring) that was hit, or null if the touch missed all rings|null| +|touchedRingIndex| index of the hit ring, or `-1` when no ring was hit|required| +|touchAngle| angle of the touch in degrees (same convention as `startDegreeOffset`: 0° points right)|required| +|touchRadius| distance from the gauge's center to the touch in pixels|required| +|touchValue| touch position interpolated along the gauge's scale, in `[minValue, maxValue]`|required| +|isOnValue| true when a [GaugeProgressRing](#GaugeProgressRing) was hit AND the touch sits on its filled portion; false otherwise (including zones-ring hits and misses)|required| +|touchedZone| the [GaugeZone](#GaugeZone) hit when the touched ring is a [GaugeZonesRing](#GaugeZonesRing) and the touch falls inside one of its bands|null| +|touchedZoneIndex| index of `touchedZone` in the hit ring's `zones` list, or `-1`|-1| diff --git a/repo_files/documentations/index.md b/repo_files/documentations/index.md index f36e83e6c..7a8eba669 100644 --- a/repo_files/documentations/index.md +++ b/repo_files/documentations/index.md @@ -14,6 +14,8 @@ Click and learn more about them. - [CandlestickChart](candlestick_chart.md) +- [GaugeChart](gauge_chart.md) + ----------- - [Migration Guides](migration_guides/INDEX.md) diff --git a/test/chart/bar_chart/bar_chart_renderer_test.mocks.dart b/test/chart/bar_chart/bar_chart_renderer_test.mocks.dart index bd7740a16..e39c15982 100644 --- a/test/chart/bar_chart/bar_chart_renderer_test.mocks.dart +++ b/test/chart/bar_chart/bar_chart_renderer_test.mocks.dart @@ -44,8 +44,9 @@ class _FakeRect_0 extends _i1.SmartFake implements _i2.Rect { ); } -class _FakeCanvas_1 extends _i1.SmartFake implements _i2.Canvas { - _FakeCanvas_1( +class _FakePictureRecorder_1 extends _i1.SmartFake + implements _i2.PictureRecorder { + _FakePictureRecorder_1( Object parent, Invocation parentInvocation, ) : super( @@ -54,9 +55,19 @@ class _FakeCanvas_1 extends _i1.SmartFake implements _i2.Canvas { ); } -class _FakePaintingContext_2 extends _i1.SmartFake +class _FakeCanvas_2 extends _i1.SmartFake implements _i2.Canvas { + _FakeCanvas_2( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakePaintingContext_3 extends _i1.SmartFake implements _i3.PaintingContext { - _FakePaintingContext_2( + _FakePaintingContext_3( Object parent, Invocation parentInvocation, ) : super( @@ -65,9 +76,9 @@ class _FakePaintingContext_2 extends _i1.SmartFake ); } -class _FakeColorFilterLayer_3 extends _i1.SmartFake +class _FakeColorFilterLayer_4 extends _i1.SmartFake implements _i4.ColorFilterLayer { - _FakeColorFilterLayer_3( + _FakeColorFilterLayer_4( Object parent, Invocation parentInvocation, ) : super( @@ -80,8 +91,8 @@ class _FakeColorFilterLayer_3 extends _i1.SmartFake super.toString(); } -class _FakeOpacityLayer_4 extends _i1.SmartFake implements _i4.OpacityLayer { - _FakeOpacityLayer_4( +class _FakeOpacityLayer_5 extends _i1.SmartFake implements _i4.OpacityLayer { + _FakeOpacityLayer_5( Object parent, Invocation parentInvocation, ) : super( @@ -94,8 +105,8 @@ class _FakeOpacityLayer_4 extends _i1.SmartFake implements _i4.OpacityLayer { super.toString(); } -class _FakeWidget_5 extends _i1.SmartFake implements _i6.Widget { - _FakeWidget_5( +class _FakeWidget_6 extends _i1.SmartFake implements _i6.Widget { + _FakeWidget_6( Object parent, Invocation parentInvocation, ) : super( @@ -108,9 +119,9 @@ class _FakeWidget_5 extends _i1.SmartFake implements _i6.Widget { super.toString(); } -class _FakeInheritedWidget_6 extends _i1.SmartFake +class _FakeInheritedWidget_7 extends _i1.SmartFake implements _i6.InheritedWidget { - _FakeInheritedWidget_6( + _FakeInheritedWidget_7( Object parent, Invocation parentInvocation, ) : super( @@ -123,9 +134,9 @@ class _FakeInheritedWidget_6 extends _i1.SmartFake super.toString(); } -class _FakeDiagnosticsNode_7 extends _i1.SmartFake +class _FakeDiagnosticsNode_8 extends _i1.SmartFake implements _i5.DiagnosticsNode { - _FakeDiagnosticsNode_7( + _FakeDiagnosticsNode_8( Object parent, Invocation parentInvocation, ) : super( @@ -141,8 +152,8 @@ class _FakeDiagnosticsNode_7 extends _i1.SmartFake super.toString(); } -class _FakeOffset_8 extends _i1.SmartFake implements _i2.Offset { - _FakeOffset_8( +class _FakeOffset_9 extends _i1.SmartFake implements _i2.Offset { + _FakeOffset_9( Object parent, Invocation parentInvocation, ) : super( @@ -784,10 +795,19 @@ class MockPaintingContext extends _i1.Mock implements _i3.PaintingContext { ), ) as _i2.Rect); + @override + _i2.PictureRecorder get recorder => (super.noSuchMethod( + Invocation.getter(#recorder), + returnValue: _FakePictureRecorder_1( + this, + Invocation.getter(#recorder), + ), + ) as _i2.PictureRecorder); + @override _i2.Canvas get canvas => (super.noSuchMethod( Invocation.getter(#canvas), - returnValue: _FakeCanvas_1( + returnValue: _FakeCanvas_2( this, Invocation.getter(#canvas), ), @@ -897,7 +917,7 @@ class MockPaintingContext extends _i1.Mock implements _i3.PaintingContext { bounds, ], ), - returnValue: _FakePaintingContext_2( + returnValue: _FakePaintingContext_3( this, Invocation.method( #createChildContext, @@ -1024,7 +1044,7 @@ class MockPaintingContext extends _i1.Mock implements _i3.PaintingContext { ], {#oldLayer: oldLayer}, ), - returnValue: _FakeColorFilterLayer_3( + returnValue: _FakeColorFilterLayer_4( this, Invocation.method( #pushColorFilter, @@ -1074,7 +1094,7 @@ class MockPaintingContext extends _i1.Mock implements _i3.PaintingContext { ], {#oldLayer: oldLayer}, ), - returnValue: _FakeOpacityLayer_4( + returnValue: _FakeOpacityLayer_5( this, Invocation.method( #pushOpacity, @@ -1180,7 +1200,7 @@ class MockBuildContext extends _i1.Mock implements _i6.BuildContext { @override _i6.Widget get widget => (super.noSuchMethod( Invocation.getter(#widget), - returnValue: _FakeWidget_5( + returnValue: _FakeWidget_6( this, Invocation.getter(#widget), ), @@ -1209,7 +1229,7 @@ class MockBuildContext extends _i1.Mock implements _i6.BuildContext { [ancestor], {#aspect: aspect}, ), - returnValue: _FakeInheritedWidget_6( + returnValue: _FakeInheritedWidget_7( this, Invocation.method( #dependOnInheritedElement, @@ -1259,7 +1279,7 @@ class MockBuildContext extends _i1.Mock implements _i6.BuildContext { [name], {#style: style}, ), - returnValue: _FakeDiagnosticsNode_7( + returnValue: _FakeDiagnosticsNode_8( this, Invocation.method( #describeElement, @@ -1280,7 +1300,7 @@ class MockBuildContext extends _i1.Mock implements _i6.BuildContext { [name], {#style: style}, ), - returnValue: _FakeDiagnosticsNode_7( + returnValue: _FakeDiagnosticsNode_8( this, Invocation.method( #describeWidget, @@ -1309,7 +1329,7 @@ class MockBuildContext extends _i1.Mock implements _i6.BuildContext { #describeOwnershipChain, [name], ), - returnValue: _FakeDiagnosticsNode_7( + returnValue: _FakeDiagnosticsNode_8( this, Invocation.method( #describeOwnershipChain, @@ -1381,6 +1401,26 @@ class MockBarChartPainter extends _i1.Mock implements _i10.BarChartPainter { returnValueForMissingStub: null, ); + @override + void drawBarLabels( + _i6.BuildContext? context, + _i11.CanvasWrapper? canvasWrapper, + List<_i10.GroupBarsPosition>? groupBarsPosition, + _i12.PaintHolder<_i13.BarChartData>? holder, + ) => + super.noSuchMethod( + Invocation.method( + #drawBarLabels, + [ + context, + canvasWrapper, + groupBarsPosition, + holder, + ], + ), + returnValueForMissingStub: null, + ); + @override void drawErrorIndicatorData( _i11.CanvasWrapper? canvasWrapper, @@ -1665,7 +1705,7 @@ class MockBarChartPainter extends _i1.Mock implements _i10.BarChartPainter { holder, ], ), - returnValue: _FakeOffset_8( + returnValue: _FakeOffset_9( this, Invocation.method( #getChartCoordinateFromPixel, diff --git a/test/chart/candlestick_chart/candlestick_chart_renderer_test.mocks.dart b/test/chart/candlestick_chart/candlestick_chart_renderer_test.mocks.dart index ca15865e9..03fdf14e3 100644 --- a/test/chart/candlestick_chart/candlestick_chart_renderer_test.mocks.dart +++ b/test/chart/candlestick_chart/candlestick_chart_renderer_test.mocks.dart @@ -45,8 +45,9 @@ class _FakeRect_0 extends _i1.SmartFake implements _i2.Rect { ); } -class _FakeCanvas_1 extends _i1.SmartFake implements _i2.Canvas { - _FakeCanvas_1( +class _FakePictureRecorder_1 extends _i1.SmartFake + implements _i2.PictureRecorder { + _FakePictureRecorder_1( Object parent, Invocation parentInvocation, ) : super( @@ -55,9 +56,19 @@ class _FakeCanvas_1 extends _i1.SmartFake implements _i2.Canvas { ); } -class _FakePaintingContext_2 extends _i1.SmartFake +class _FakeCanvas_2 extends _i1.SmartFake implements _i2.Canvas { + _FakeCanvas_2( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakePaintingContext_3 extends _i1.SmartFake implements _i3.PaintingContext { - _FakePaintingContext_2( + _FakePaintingContext_3( Object parent, Invocation parentInvocation, ) : super( @@ -66,9 +77,9 @@ class _FakePaintingContext_2 extends _i1.SmartFake ); } -class _FakeColorFilterLayer_3 extends _i1.SmartFake +class _FakeColorFilterLayer_4 extends _i1.SmartFake implements _i4.ColorFilterLayer { - _FakeColorFilterLayer_3( + _FakeColorFilterLayer_4( Object parent, Invocation parentInvocation, ) : super( @@ -81,8 +92,8 @@ class _FakeColorFilterLayer_3 extends _i1.SmartFake super.toString(); } -class _FakeOpacityLayer_4 extends _i1.SmartFake implements _i4.OpacityLayer { - _FakeOpacityLayer_4( +class _FakeOpacityLayer_5 extends _i1.SmartFake implements _i4.OpacityLayer { + _FakeOpacityLayer_5( Object parent, Invocation parentInvocation, ) : super( @@ -95,8 +106,8 @@ class _FakeOpacityLayer_4 extends _i1.SmartFake implements _i4.OpacityLayer { super.toString(); } -class _FakeWidget_5 extends _i1.SmartFake implements _i6.Widget { - _FakeWidget_5( +class _FakeWidget_6 extends _i1.SmartFake implements _i6.Widget { + _FakeWidget_6( Object parent, Invocation parentInvocation, ) : super( @@ -109,9 +120,9 @@ class _FakeWidget_5 extends _i1.SmartFake implements _i6.Widget { super.toString(); } -class _FakeInheritedWidget_6 extends _i1.SmartFake +class _FakeInheritedWidget_7 extends _i1.SmartFake implements _i6.InheritedWidget { - _FakeInheritedWidget_6( + _FakeInheritedWidget_7( Object parent, Invocation parentInvocation, ) : super( @@ -124,9 +135,9 @@ class _FakeInheritedWidget_6 extends _i1.SmartFake super.toString(); } -class _FakeDiagnosticsNode_7 extends _i1.SmartFake +class _FakeDiagnosticsNode_8 extends _i1.SmartFake implements _i5.DiagnosticsNode { - _FakeDiagnosticsNode_7( + _FakeDiagnosticsNode_8( Object parent, Invocation parentInvocation, ) : super( @@ -142,8 +153,8 @@ class _FakeDiagnosticsNode_7 extends _i1.SmartFake super.toString(); } -class _FakeOffset_8 extends _i1.SmartFake implements _i2.Offset { - _FakeOffset_8( +class _FakeOffset_9 extends _i1.SmartFake implements _i2.Offset { + _FakeOffset_9( Object parent, Invocation parentInvocation, ) : super( @@ -785,10 +796,19 @@ class MockPaintingContext extends _i1.Mock implements _i3.PaintingContext { ), ) as _i2.Rect); + @override + _i2.PictureRecorder get recorder => (super.noSuchMethod( + Invocation.getter(#recorder), + returnValue: _FakePictureRecorder_1( + this, + Invocation.getter(#recorder), + ), + ) as _i2.PictureRecorder); + @override _i2.Canvas get canvas => (super.noSuchMethod( Invocation.getter(#canvas), - returnValue: _FakeCanvas_1( + returnValue: _FakeCanvas_2( this, Invocation.getter(#canvas), ), @@ -898,7 +918,7 @@ class MockPaintingContext extends _i1.Mock implements _i3.PaintingContext { bounds, ], ), - returnValue: _FakePaintingContext_2( + returnValue: _FakePaintingContext_3( this, Invocation.method( #createChildContext, @@ -1025,7 +1045,7 @@ class MockPaintingContext extends _i1.Mock implements _i3.PaintingContext { ], {#oldLayer: oldLayer}, ), - returnValue: _FakeColorFilterLayer_3( + returnValue: _FakeColorFilterLayer_4( this, Invocation.method( #pushColorFilter, @@ -1075,7 +1095,7 @@ class MockPaintingContext extends _i1.Mock implements _i3.PaintingContext { ], {#oldLayer: oldLayer}, ), - returnValue: _FakeOpacityLayer_4( + returnValue: _FakeOpacityLayer_5( this, Invocation.method( #pushOpacity, @@ -1181,7 +1201,7 @@ class MockBuildContext extends _i1.Mock implements _i6.BuildContext { @override _i6.Widget get widget => (super.noSuchMethod( Invocation.getter(#widget), - returnValue: _FakeWidget_5( + returnValue: _FakeWidget_6( this, Invocation.getter(#widget), ), @@ -1210,7 +1230,7 @@ class MockBuildContext extends _i1.Mock implements _i6.BuildContext { [ancestor], {#aspect: aspect}, ), - returnValue: _FakeInheritedWidget_6( + returnValue: _FakeInheritedWidget_7( this, Invocation.method( #dependOnInheritedElement, @@ -1260,7 +1280,7 @@ class MockBuildContext extends _i1.Mock implements _i6.BuildContext { [name], {#style: style}, ), - returnValue: _FakeDiagnosticsNode_7( + returnValue: _FakeDiagnosticsNode_8( this, Invocation.method( #describeElement, @@ -1281,7 +1301,7 @@ class MockBuildContext extends _i1.Mock implements _i6.BuildContext { [name], {#style: style}, ), - returnValue: _FakeDiagnosticsNode_7( + returnValue: _FakeDiagnosticsNode_8( this, Invocation.method( #describeWidget, @@ -1310,7 +1330,7 @@ class MockBuildContext extends _i1.Mock implements _i6.BuildContext { #describeOwnershipChain, [name], ), - returnValue: _FakeDiagnosticsNode_7( + returnValue: _FakeDiagnosticsNode_8( this, Invocation.method( #describeOwnershipChain, @@ -1633,7 +1653,7 @@ class MockCandlestickChartPainter extends _i1.Mock holder, ], ), - returnValue: _FakeOffset_8( + returnValue: _FakeOffset_9( this, Invocation.method( #getChartCoordinateFromPixel, diff --git a/test/chart/data_pool.dart b/test/chart/data_pool.dart index a32c8a5c3..832cbb8af 100644 --- a/test/chart/data_pool.dart +++ b/test/chart/data_pool.dart @@ -4,1637 +4,1246 @@ import 'package:fl_chart/fl_chart.dart'; import 'package:fl_chart/src/chart/base/line.dart'; import 'package:flutter/material.dart'; -class MockData { - static const color0 = Color(0x00000000); - static const color1 = Color(0x11111111); - static const color2 = Color(0x22222222); - static const color3 = Color(0x33333333); - static const color4 = Color(0x44444444); - static const color5 = Color(0x55555555); - static const color6 = Color(0x66666666); +const BarAreaSpotsLine barAreaSpotsLine1 = + BarAreaSpotsLine(show: true, checkToShowSpotLine: checkToShowSpotLine); - static final path1 = Path() - ..moveTo(10, 10) - ..lineTo(20, 20) - ..arcTo( - Rect.fromCenter(center: Offset.zero, width: 44, height: 22), - 2, - 3, - false, - ); +const BarAreaSpotsLine barAreaSpotsLine1Clone = + BarAreaSpotsLine(show: true, checkToShowSpotLine: checkToShowSpotLine); +const BarAreaSpotsLine barAreaSpotsLine2 = BarAreaSpotsLine( + show: true, +); - static final path1Duplicate = Path() - ..moveTo(10, 10) - ..lineTo(20, 20) - ..arcTo( - Rect.fromCenter(center: Offset.zero, width: 44, height: 22), - 2, - 3, - false, - ); +const BarTouchData barTouchData2 = BarTouchData( + handleBuiltInTouches: false, + touchCallback: barTouchCallback, + enabled: false, + allowTouchBarBackDraw: true, + touchExtraThreshold: EdgeInsets.all(12), +); +const FlDotData flDotData1 = FlDotData( + getDotPainter: getDotDrawer, + checkToShowDot: checkToShowDot, +); - static final path2 = Path() - ..moveTo(10, 10) - ..lineTo(20, 20) - ..arcTo( - Rect.fromCenter(center: Offset.zero, width: 44, height: 22.01), - 2, - 3, - false, - ); +const FlDotData flDotData1Clone = FlDotData( + getDotPainter: getDotDrawer, + checkToShowDot: checkToShowDot, +); +const FlDotData flDotData4 = FlDotData( + getDotPainter: getDotDrawer, +); +const FlDotData flDotData5 = FlDotData( + getDotPainter: getDotDrawer5, +); - static final path3 = Path() - ..moveTo(10, 13) - ..lineTo(20, 20) - ..arcTo( - Rect.fromCenter(center: Offset.zero, width: 44, height: 22), - 2, - 3, - false, - ); +const FlDotData flDotData6 = FlDotData( + getDotPainter: getDotDrawer6, +); +const FlGridData flGridData1 = FlGridData( + verticalInterval: 12, + horizontalInterval: 22, + drawVerticalLine: false, + checkToShowVerticalLine: checkToShowLine, + getDrawingHorizontalLine: getDrawingLine, +); - static final path4 = Path() - ..moveTo(24, 13) - ..lineTo(20, 20) - ..arcTo( - Rect.fromCenter(center: Offset.zero, width: 44, height: 22), - 2, - 3, - false, - ); +const FlGridData flGridData1Clone = FlGridData( + verticalInterval: 12, + horizontalInterval: 22, + drawVerticalLine: false, + checkToShowVerticalLine: checkToShowLine, + getDrawingHorizontalLine: getDrawingLine, +); - static const borderSide1 = BorderSide(color: color1); - static const borderSide2 = BorderSide(color: color2, width: 2); - static const borderSide3 = BorderSide(color: color3, width: 3); - static const borderSide4 = BorderSide(color: color4, width: 4); - static const borderSide5 = BorderSide(color: color5, width: 5); - static const borderSide6 = BorderSide(color: color6, width: 6); +const FlGridData flGridData3 = FlGridData( + verticalInterval: 12, + horizontalInterval: 43, + drawVerticalLine: false, + checkToShowVerticalLine: checkToShowLine, + getDrawingHorizontalLine: getDrawingLine, +); - static const TextStyle textStyle1 = - TextStyle(color: color1, fontWeight: FontWeight.w100); - static const TextStyle textStyle2 = - TextStyle(color: color2, fontWeight: FontWeight.w200); - static const TextStyle textStyle3 = - TextStyle(color: color3, fontWeight: FontWeight.w300); - static const TextStyle textStyle4 = - TextStyle(color: color4, fontWeight: FontWeight.w400); +const FlGridData flGridData4 = FlGridData( + verticalInterval: 12, + horizontalInterval: 22, + drawVerticalLine: false, + getDrawingHorizontalLine: getDrawingLine, +); +const FlGridData flGridData5 = FlGridData( + verticalInterval: 12, + horizontalInterval: 22, + checkToShowVerticalLine: checkToShowLine, + getDrawingHorizontalLine: getDrawingLine, +); - static const Offset offset1 = Offset(1, 1); - static const Offset offset1Duplicate = Offset(1, 1); - static const Offset offset2 = Offset(2, 2); - static const Offset offset3 = Offset(2, 2); - static const Offset offset4 = Offset(4, 4); - static const Offset offset5 = Offset(5, 5); - static const Offset offset6 = Offset(6, 6); +const FlLine flLine1 = + FlLine(color: Colors.green, strokeWidth: 1, dashArray: [1, 2, 3]); +const FlLine flLine1Clone = + FlLine(color: Colors.green, strokeWidth: 1, dashArray: [1, 2, 3]); - static const size1 = Size(11, 11); - static const size2 = Size(22, 22); +const FlSpot flSpot1 = FlSpot(1, 1); +const FlSpot flSpot2 = FlSpot(4, 2); - static final textPainter1 = TextPainter(); - static final textPainter2 = TextPainter() - ..text = const TextSpan(text: 'test') - ..textDirection = TextDirection.ltr - ..layout(); +const Line line1 = Line(Offset.zero, Offset(10, 10)); - static final rect1 = Rect.fromCenter(center: offset1, width: 11, height: 11); - static final rect2 = Rect.fromCenter(center: offset2, width: 22, height: 22); +const Line line2 = Line(Offset(-4, -12), Offset(6, 8)); - static final rRect1 = RRect.fromLTRBR(1, 1, 1, 1, const Radius.circular(11)); - static final rRect2 = RRect.fromLTRBR(2, 2, 2, 2, const Radius.circular(22)); +const Line line3 = Line(Offset(18, -1), Offset.zero); +const Line line4 = Line(Offset(8, 8), Offset(-4, -22)); +const Line line5 = Line(Offset(2, 3), Offset(5, 8)); +const LineChartStepData lineChartStepData1 = LineChartStepData(); +const LineChartStepData lineChartStepData1Clone = LineChartStepData(); +const LineChartStepData lineChartStepData2 = LineChartStepData( + stepDirection: LineChartStepData.stepDirectionForward, +); - static final paint1 = Paint() - ..color = color1 - ..strokeWidth = 11; - static final paint2 = Paint() - ..color = color2 - ..strokeWidth = 22; +const LineTooltipItem lineTooltipItem1 = + LineTooltipItem('', TextStyle(color: Colors.green)); +const LineTooltipItem lineTooltipItem1Clone = + LineTooltipItem('', TextStyle(color: Colors.green)); +const LineTooltipItem lineTooltipItem2 = + LineTooltipItem('ss', TextStyle(color: Colors.green)); - static Picture? _picture1; +const LineTooltipItem lineTooltipItem3 = + LineTooltipItem('', TextStyle(color: Colors.blue)); - static Picture picture1() { - if (_picture1 != null) { - return _picture1!; - } - final recorder1 = PictureRecorder(); - Canvas(recorder1).drawLine(offset1, offset2, paint1); - _picture1 = recorder1.endRecording(); - return _picture1!; - } +const LineTooltipItem lineTooltipItem4 = + LineTooltipItem('', TextStyle(fontSize: 33)); +const LineTouchData lineTouchData4 = LineTouchData( + touchCallback: lineTouchCallback, + getTouchedSpotIndicator: getTouchedSpotIndicator, + handleBuiltInTouches: false, + touchSpotThreshold: 12, +); - static Image? _image1; +const FlSpot nullSpot1 = FlSpot.nullSpot; - static Image image1() { - if (_image1 != null) { - return _image1!; - } - _image1 = Image.asset('asdf/asdf'); - return _image1!; - } +const FlSpot nullSpot3 = FlSpot.nullSpot; +const Shadow shadow1 = Shadow( + color: Colors.red, + blurRadius: 12, +); - static final LineChartBarData lineChartBarData1 = LineChartBarData( - dashArray: [0, 1], - gradient: const LinearGradient( - colors: [Colors.red, Colors.green], - stops: [0, 1], - begin: Alignment.center, - end: Alignment.bottomRight, - ), - spots: [ - flSpot1, - flSpot2, - ], - shadow: shadow1, - aboveBarData: barAreaData1, - belowBarData: barAreaData2, - barWidth: 12, - curveSmoothness: 12, - dotData: flDotData1, - isStrokeCapRound: true, - preventCurveOvershootingThreshold: 1.2, - showingIndicators: [0, 1], - ); +const Shadow shadow1Clone = Shadow( + color: Colors.red, + blurRadius: 12, +); +const Shadow shadow2 = Shadow( + color: Colors.green, + blurRadius: 12, +); +const Shadow shadow3 = Shadow( + color: Colors.red, + blurRadius: 14, +); - static final LineChartBarData lineChartBarData2 = LineChartBarData( - dashArray: [0, 1], - gradient: const LinearGradient( - colors: [Colors.red, Colors.green], - stops: [0, 1], - begin: Alignment.center, - end: Alignment.bottomRight, - ), - spots: [ - flSpot1, - flSpot2, - ], - shadow: shadow2, - isStepLineChart: true, - aboveBarData: barAreaData1, - belowBarData: barAreaData2, - barWidth: 12, - curveSmoothness: 12, - dotData: flDotData1, - isStrokeCapRound: true, - preventCurveOvershootingThreshold: 1.2, - showingIndicators: [0, 4], - ); - - static const FlSpot flSpot0 = FlSpot.zero; - static const flSpot1 = FlSpot(1, 1); - static const flSpot2 = FlSpot(2, 2); - static const flSpot3 = FlSpot(3, 3); - static const flSpot4 = FlSpot(4, 4); - static const flSpot5 = FlSpot(5, 5); - - static final horizontalLine0 = HorizontalLine(y: 0, color: color0); - static final horizontalLine1 = HorizontalLine(y: 1, color: color1); - static final horizontalLine2 = HorizontalLine(y: 2, color: color2); - static final horizontalLine3 = HorizontalLine(y: 3, color: color3); - static final horizontalLine4 = HorizontalLine(y: 4, color: color4); - static final horizontalLine5 = HorizontalLine(y: 5, color: color5); - - static final verticalLine0 = VerticalLine(x: 0, color: color0); - static final verticalLine1 = VerticalLine(x: 1, color: color1); - static final verticalLine2 = VerticalLine(x: 2, color: color2); - static final verticalLine3 = VerticalLine(x: 3, color: color3); - static final verticalLine4 = VerticalLine(x: 4, color: color4); - static final verticalLine5 = VerticalLine(x: 5, color: color5); - - static final horizontalRangeAnnotation0 = - HorizontalRangeAnnotation(y1: 0, y2: 1, color: color0); - - static final horizontalRangeAnnotation1 = - HorizontalRangeAnnotation(y1: 1, y2: 2, color: color1); +const ShowingTooltipIndicators showingTooltipIndicator2 = + ShowingTooltipIndicators( + [], +); - static final horizontalRangeAnnotation2 = - HorizontalRangeAnnotation(y1: 2, y2: 3, color: color2); +const TextSpan textSpan1 = TextSpan(text: 'faketext1', style: textStyle1); - static final horizontalRangeAnnotation3 = - HorizontalRangeAnnotation(y1: 3, y2: 4, color: color3); +const TextSpan textSpan2 = TextSpan(text: 'faketext2', style: textStyle2); - static final horizontalRangeAnnotation4 = - HorizontalRangeAnnotation(y1: 4, y2: 5, color: color4); +const TextStyle textStyle1 = + TextStyle(color: Colors.red, fontWeight: FontWeight.bold); - static final verticalRangeAnnotation0 = - VerticalRangeAnnotation(x1: 0, x2: 1, color: color0); +const TextStyle textStyle2 = + TextStyle(color: Colors.green, fontWeight: FontWeight.w200); - static final verticalRangeAnnotation1 = - VerticalRangeAnnotation(x1: 1, x2: 2, color: color1); +const TouchedSpotIndicatorData touchedSpotIndicatorData1 = + TouchedSpotIndicatorData( + FlLine( + color: Colors.red, + dashArray: [], + ), + FlDotData( + getDotPainter: getDotDrawerTouched, + checkToShowDot: checkToShowDot, + ), +); - static final verticalRangeAnnotation2 = - VerticalRangeAnnotation(x1: 2, x2: 3, color: color2); +const TouchedSpotIndicatorData touchedSpotIndicatorData1Clone = + TouchedSpotIndicatorData( + FlLine( + color: Colors.red, + dashArray: [], + ), + FlDotData( + getDotPainter: getDotDrawerTouched, + checkToShowDot: checkToShowDot, + ), +); - static final verticalRangeAnnotation3 = - VerticalRangeAnnotation(x1: 3, x2: 4, color: color3); +const TouchedSpotIndicatorData touchedSpotIndicatorData2 = + TouchedSpotIndicatorData( + FlLine( + color: Colors.red, + dashArray: [], + ), + FlDotData( + getDotPainter: getDotDrawerTouched, + ), +); +const TouchedSpotIndicatorData touchedSpotIndicatorData3 = + TouchedSpotIndicatorData( + FlLine( + color: Colors.red, + ), + FlDotData( + getDotPainter: getDotDrawerTouched, + checkToShowDot: checkToShowDot, + ), +); - static final verticalRangeAnnotation4 = - VerticalRangeAnnotation(x1: 4, x2: 5, color: color4); +const TouchedSpotIndicatorData touchedSpotIndicatorData4 = + TouchedSpotIndicatorData( + FlLine( + color: Colors.green, + dashArray: [], + ), + FlDotData( + getDotPainter: getDotDrawerTouched4, + checkToShowDot: checkToShowDot, + ), +); - static const RadarEntry radarEntry0 = RadarEntry(value: 0); - static const RadarEntry radarEntry1 = RadarEntry(value: 1); - static const RadarEntry radarEntry2 = RadarEntry(value: 2); - static const RadarEntry radarEntry3 = RadarEntry(value: 3); - static const RadarEntry radarEntry4 = RadarEntry(value: 4); - static final RadarDataSet radarDataSet1 = RadarDataSet( - dataEntries: [radarEntry1, radarEntry2, radarEntry3], - ); - static final RadarDataSet radarDataSet2 = RadarDataSet( - dataEntries: [radarEntry3, radarEntry1, radarEntry2], - ); - static final RadarTouchedSpot radarTouchedSpot = RadarTouchedSpot( - radarDataSet1, - 0, - radarEntry1, - 0, - flSpot1, - offset1, - ); +const TouchedSpotIndicatorData touchedSpotIndicatorData5 = + TouchedSpotIndicatorData( + FlLine( + color: Colors.red, + dashArray: [], + ), + FlDotData( + getDotPainter: getDotDrawerTouched, + checkToShowDot: checkToShowDot, + show: false, + ), +); - static final pieChartSection0 = PieChartSectionData( - value: 0, - color: color0, - radius: 0, - ); +const TouchedSpotIndicatorData touchedSpotIndicatorData6 = + TouchedSpotIndicatorData( + FlLine( + color: Colors.red, + dashArray: [], + ), + FlDotData( + getDotPainter: getDotDrawerTouched6, + checkToShowDot: checkToShowDot, + ), +); - static final pieChartSection1 = PieChartSectionData( - value: 1, - color: color1, - radius: 1, - ); +final BackgroundBarChartRodData backgroundBarChartRodData1 = + BackgroundBarChartRodData( + toY: 21, + color: Colors.blue, + show: true, +); +final BackgroundBarChartRodData backgroundBarChartRodData1Clone = + BackgroundBarChartRodData( + toY: 21, + color: Colors.blue, + show: true, +); +final BackgroundBarChartRodData backgroundBarChartRodData2 = + BackgroundBarChartRodData( + toY: 44, + color: Colors.red, + show: true, +); +final BackgroundBarChartRodData backgroundBarChartRodData3 = + BackgroundBarChartRodData( + toY: 44, + color: Colors.green, + show: true, +); +final BarAreaData barAreaData1 = BarAreaData( + show: true, + cutOffY: 12, + gradient: const LinearGradient( + colors: [Colors.green, Colors.blue], + stops: [0, 0.5], + begin: Alignment.topLeft, + end: Alignment.bottomCenter, + ), + spotsLine: barAreaSpotsLine1, +); - static final pieChartSection2 = PieChartSectionData( - value: 2, - color: color2, - radius: 2, - ); +final BarAreaData barAreaData1Clone = BarAreaData( + show: true, + cutOffY: 12, + gradient: const LinearGradient( + colors: [Colors.green, Colors.blue], + stops: [0, 0.5], + begin: Alignment.topLeft, + end: Alignment.bottomCenter, + ), + spotsLine: barAreaSpotsLine1, +); - static final pieChartSection3 = PieChartSectionData( - value: 3, - color: color3, - radius: 3, - ); +final BarAreaData barAreaData2 = BarAreaData( + show: true, + cutOffY: 12, + gradient: const LinearGradient( + colors: [Colors.green, Colors.blue], + stops: [0, 0.5], + begin: Alignment.topLeft, + end: Alignment.bottomCenter, + ), + spotsLine: barAreaSpotsLine2, +); - static final pieChartSection4 = PieChartSectionData( - value: 4, - color: color4, - radius: 4, - ); +final BarAreaData barAreaData3 = BarAreaData( + show: true, + cutOffY: 12, + gradient: const LinearGradient( + colors: [Colors.green, Colors.blue], + stops: [0, 0.6], + begin: Alignment.topLeft, + end: Alignment.bottomCenter, + ), + spotsLine: barAreaSpotsLine2, +); - static final scatterSpot0 = ScatterSpot( - 0, - 0, - dotPainter: FlDotCirclePainter(color: color0), - ); - static final scatterSpot1 = ScatterSpot( - 1, - 1, - dotPainter: FlDotCirclePainter(color: color1), - ); - static final scatterSpot2 = ScatterSpot( - 2, - 2, - dotPainter: FlDotCirclePainter(color: color2), - ); - static final scatterSpot3 = ScatterSpot( - 3, - 3, - dotPainter: FlDotCirclePainter(color: color3), - ); - static final scatterSpot4 = ScatterSpot( - 4, - 4, - dotPainter: FlDotCirclePainter(color: color4), - ); - - static final scatterTouchedSpot = ScatterTouchedSpot(scatterSpot1, 0); +final BarAreaData barAreaData4 = BarAreaData( + show: true, + cutOffY: 12, + gradient: const LinearGradient( + colors: [Colors.green, Colors.blue], + stops: [0], + begin: Alignment.topLeft, + end: Alignment.bottomCenter, + ), + spotsLine: barAreaSpotsLine2, +); +final BarChartData barChartData1 = BarChartData( + minY: 12, + titlesData: MockData.flTitlesData1, + gridData: flGridData1, + rangeAnnotations: rangeAnnotations1, + maxY: 23, + backgroundColor: Colors.green, + borderData: borderData1, + alignment: BarChartAlignment.spaceAround, + barGroups: [ + barChartGroupData1, + barChartGroupData2, + barChartGroupData3, + ], + barTouchData: barTouchData1, + groupsSpace: 23, + extraLinesData: extraLinesData1, +); - static final pieChartSectionData1 = PieChartSectionData(value: 12); +final BarChartData barChartData10 = barChartData1.copyWith( + alignment: BarChartAlignment.center, +); - static final pieChartSectionData2 = PieChartSectionData(value: 22); +final BarChartData barChartData11 = barChartData1.copyWith( + barGroups: [], +); - static final pieTouchedSection1 = PieTouchedSection( - pieChartSectionData1, - 0, - 12, - 33, - ); +final BarChartData barChartData12 = barChartData1.copyWith( + barGroups: [ + barChartGroupData3, + barChartGroupData1, + barChartGroupData2, + ], +); - static final lineBarSpot1 = TouchLineBarSpot( - lineChartBarData1, - 0, - lineChartBarData1.spots.first, - 0, - ); - static final lineBarSpot2 = TouchLineBarSpot( - MockData.lineChartBarData1, - 1, - MockData.lineChartBarData1.spots.last, - 2, - ); +final BarChartData barChartData13 = barChartData1.copyWith( + barTouchData: barTouchData2, +); - static final lineTouchResponse1 = LineTouchResponse( - touchLocation: Offset.zero, - touchChartCoordinate: Offset.zero, - lineBarSpots: [lineBarSpot1, lineBarSpot2], - ); +final BarChartData barChartData14 = barChartData1.copyWith( + groupsSpace: 444, +); - static final barChartRodData1 = BarChartRodData(toY: 11); - static final barChartRodData2 = BarChartRodData(toY: 22); - static final barTouchedSpot = BarTouchedSpot( - BarChartGroupData(x: 0, barRods: [barChartRodData1, barChartRodData2]), - 0, - barChartRodData1, - 0, - null, - -1, - flSpot1, - offset1, - ); +final BarChartData barChartData15 = barChartData1.copyWith( + extraLinesData: extraLinesData2, +); - static const gradient1 = LinearGradient( - colors: [ - MockData.color0, - MockData.color1, - ], - ); +final BarChartData barChartData1Clone = barChartData1.copyWith( + titlesData: MockData.flTitlesData1Clone, + gridData: flGridData1Clone, + borderData: borderData1Clone, + barTouchData: barTouchData1Clone, + rangeAnnotations: rangeAnnotations1Clone, +); - static final barGroupData0 = BarChartGroupData( - x: 0, - barRods: [MockData.barChartRodData1, MockData.barChartRodData2], - ); +final BarChartData barChartData2 = barChartData1.copyWith( + minY: 11, +); - static final barGroupData1 = BarChartGroupData( - x: 1, - barRods: [MockData.barChartRodData1, MockData.barChartRodData2], - ); +final BarChartData barChartData3 = barChartData1.copyWith( + titlesData: MockData.flTitlesData2, +); +final BarChartData barChartData4 = barChartData1.copyWith( + gridData: flGridData2, +); - static final barGroupData2 = BarChartGroupData( - x: 2, - barRods: [MockData.barChartRodData1, MockData.barChartRodData2], - ); +final BarChartData barChartData5 = barChartData1.copyWith( + rangeAnnotations: rangeAnnotations2, +); - static final barChartData1 = BarChartData( - barGroups: [barGroupData0, barGroupData1, barGroupData2], - ); +final BarChartData barChartData6 = barChartData1.copyWith( + maxY: 52345, +); - static const sideTitles1 = SideTitles( - reservedSize: 10, - interval: 23, - ); - static const sideTitles1Clone = SideTitles( - reservedSize: 10, - interval: 23, - ); - static const sideTitles2 = SideTitles( - reservedSize: 10, - interval: 12, - ); - static const sideTitles3 = SideTitles( - reservedSize: 10, - getTitlesWidget: getTitles, - interval: 12, - ); - static const sideTitles4 = SideTitles( - reservedSize: 11, - showTitles: true, - getTitlesWidget: getTitles, - interval: 12, - ); - static const sideTitles5 = SideTitles( - reservedSize: 10, - getTitlesWidget: getTitles, - interval: 43, - ); - static const sideTitles6 = SideTitles( - reservedSize: 10, - getTitlesWidget: getTitles, - interval: 22, - ); +final BarChartData barChartData7 = barChartData1.copyWith( + backgroundColor: Colors.red, +); +final BarChartData barChartData8 = barChartData1.copyWith( + titlesData: MockData.flTitlesData3, +); - static const sideTitleFitInsideData1 = SideTitleFitInsideData( - enabled: true, - axisPosition: 0, - parentAxisSize: 100, - distanceFromEdge: 0, - ); - static const sideTitleFitInsideData1Clone = SideTitleFitInsideData( - enabled: true, - axisPosition: 0, - parentAxisSize: 100, - distanceFromEdge: 0, - ); - static const sideTitleFitInsideData2 = SideTitleFitInsideData( - enabled: true, - axisPosition: 0, - parentAxisSize: 100, - distanceFromEdge: 10, - ); - static const sideTitleFitInsideData3 = SideTitleFitInsideData( - enabled: false, - axisPosition: 0, - parentAxisSize: 100, - distanceFromEdge: 0, - ); - static const sideTitleFitInsideData4 = SideTitleFitInsideData( - enabled: true, - axisPosition: 200, - parentAxisSize: 200, - distanceFromEdge: 0, - ); - static const sideTitleFitInsideData5 = SideTitleFitInsideData( - enabled: true, - axisPosition: 200, - parentAxisSize: 200, - distanceFromEdge: 10, - ); - static const sideTitleFitInsideData6 = SideTitleFitInsideData( - enabled: false, - axisPosition: 200, - parentAxisSize: 200, - distanceFromEdge: 0, - ); +final BarChartData barChartData9 = barChartData1.copyWith( + borderData: borderData2, +); - static const widget1 = Text('axis1'); - static const widget2 = Text('axis2'); - static const widget3 = Text('axis3'); - static const widget4 = Text('axis4'); - static const widget5 = Text('axis5'); +final BarChartGroupData barChartGroupData1 = BarChartGroupData( + x: 12, + showingTooltipIndicators: [0, 1, 2], + barRods: [ + barChartRodData1, + barChartRodData2, + barChartRodData3, + barChartRodData4, + ], + barsSpace: 23, +); - static const axisTitles1 = AxisTitles( - axisNameWidget: widget1, - sideTitles: sideTitles1, - ); - static const axisTitles1Clone = AxisTitles( - axisNameWidget: widget1, - sideTitles: sideTitles1Clone, - ); - static const axisTitles2 = AxisTitles( - axisNameWidget: widget2, - sideTitles: sideTitles2, - ); - static const axisTitles3 = AxisTitles( - axisNameWidget: widget3, - sideTitles: sideTitles3, - ); - static const axisTitles4 = AxisTitles( - axisNameWidget: widget4, - sideTitles: sideTitles4, - ); - static const axisTitles5 = AxisTitles( - axisNameWidget: widget5, - axisNameSize: 889, - sideTitles: sideTitles4, - ); - - static const flTitlesData1 = FlTitlesData( - bottomTitles: axisTitles1, - topTitles: axisTitles2, - rightTitles: axisTitles3, - leftTitles: axisTitles4, - ); - static const flTitlesData1Clone = FlTitlesData( - bottomTitles: axisTitles1Clone, - topTitles: axisTitles2, - rightTitles: axisTitles3, - leftTitles: axisTitles4, - ); - static const flTitlesData2 = FlTitlesData( - topTitles: axisTitles2, - rightTitles: axisTitles3, - leftTitles: axisTitles4, - ); - static const flTitlesData3 = FlTitlesData( - bottomTitles: axisTitles1, - rightTitles: axisTitles3, - leftTitles: axisTitles4, - ); - static const flTitlesData4 = FlTitlesData( - bottomTitles: axisTitles1, - topTitles: axisTitles2, - leftTitles: axisTitles4, - ); - static const flTitlesData5 = FlTitlesData( - bottomTitles: axisTitles1, - topTitles: axisTitles2, - rightTitles: axisTitles3, - ); - static const flTitlesData6 = FlTitlesData( - show: false, - bottomTitles: axisTitles1, - topTitles: axisTitles2, - rightTitles: axisTitles3, - leftTitles: axisTitles4, - ); -} - -final VerticalRangeAnnotation verticalRangeAnnotation1 = - VerticalRangeAnnotation(color: Colors.green, x2: 12, x1: 12.1); -final VerticalRangeAnnotation verticalRangeAnnotation1Clone = - VerticalRangeAnnotation(color: Colors.green, x2: 12, x1: 12.1); - -final HorizontalRangeAnnotation horizontalRangeAnnotation1 = - HorizontalRangeAnnotation(color: Colors.green, y2: 12, y1: 12.1); -final HorizontalRangeAnnotation horizontalRangeAnnotation1Clone = - HorizontalRangeAnnotation(color: Colors.green, y2: 12, y1: 12.1); - -final RangeAnnotations rangeAnnotations1 = RangeAnnotations( - horizontalRangeAnnotations: [ - horizontalRangeAnnotation1, - horizontalRangeAnnotation1Clone, - ], - verticalRangeAnnotations: [ - verticalRangeAnnotation1, - verticalRangeAnnotation1Clone, +final BarChartGroupData barChartGroupData1Clone = BarChartGroupData( + x: 12, + showingTooltipIndicators: [0, 1, 2], + barRods: [ + barChartRodData1Clone, + barChartRodData2, + barChartRodData3, + barChartRodData4, ], + barsSpace: 23, ); -final RangeAnnotations rangeAnnotations1Clone = RangeAnnotations( - horizontalRangeAnnotations: [ - horizontalRangeAnnotation1, - horizontalRangeAnnotation1Clone, - ], - verticalRangeAnnotations: [ - verticalRangeAnnotation1, - verticalRangeAnnotation1Clone, + +final BarChartGroupData barChartGroupData2 = BarChartGroupData( + x: 13, + showingTooltipIndicators: [0, 1, 2], + barRods: [ + barChartRodData1, + barChartRodData2, + barChartRodData3, + barChartRodData4, ], + barsSpace: 23, ); -final RangeAnnotations rangeAnnotations2 = RangeAnnotations( - horizontalRangeAnnotations: [ - horizontalRangeAnnotation1Clone, + +final BarChartGroupData barChartGroupData3 = BarChartGroupData( + x: 12, + showingTooltipIndicators: [0, 1], + barRods: [ + barChartRodData1, + barChartRodData2, + barChartRodData3, + barChartRodData4, ], - verticalRangeAnnotations: [ - verticalRangeAnnotation1, - verticalRangeAnnotation1Clone, + barsSpace: 23, +); +final BarChartGroupData barChartGroupData4 = BarChartGroupData( + x: 12, + showingTooltipIndicators: [0, 1, 2], + barRods: [ + barChartRodData1, + barChartRodData2, + barChartRodData4, ], + barsSpace: 23, ); -const FlLine flLine1 = - FlLine(color: Colors.green, strokeWidth: 1, dashArray: [1, 2, 3]); -const FlLine flLine1Clone = - FlLine(color: Colors.green, strokeWidth: 1, dashArray: [1, 2, 3]); - -bool checkToShowLine(double value) => true; - -FlLine getDrawingLine(double value) => const FlLine(); - -const FlSpot flSpot1 = FlSpot(1, 1); -final FlSpot flSpot1Clone = flSpot1.copyWith(); - -const FlSpot flSpot2 = FlSpot(4, 2); -final FlSpot flSpot2Clone = flSpot2.copyWith(); - -const FlSpot nullSpot1 = FlSpot.nullSpot; -final FlSpot nullSpot2 = nullSpot1.copyWith(); -const FlSpot nullSpot3 = FlSpot.nullSpot; - -Widget getTitles(double value, TitleMeta meta) => const Text('sallam'); - -TextStyle getTextStyles(BuildContext context, double value) => - const TextStyle(color: Colors.green); - -const FlGridData flGridData1 = FlGridData( - verticalInterval: 12, - horizontalInterval: 22, - drawVerticalLine: false, - checkToShowVerticalLine: checkToShowLine, - getDrawingHorizontalLine: getDrawingLine, -); -const FlGridData flGridData1Clone = FlGridData( - verticalInterval: 12, - horizontalInterval: 22, - drawVerticalLine: false, - checkToShowVerticalLine: checkToShowLine, - getDrawingHorizontalLine: getDrawingLine, +final BarChartGroupData barChartGroupData5 = BarChartGroupData( + x: 12, + showingTooltipIndicators: [0, 1, 2], + barsSpace: 23, ); -final FlGridData flGridData2 = FlGridData( - verticalInterval: 12, - horizontalInterval: 22, - drawVerticalLine: false, - checkToShowVerticalLine: checkToShowLine, - getDrawingHorizontalLine: getDrawingLine, - getDrawingVerticalLine: (value) => flLine1, +final BarChartGroupData barChartGroupData6 = BarChartGroupData( + x: 12, + showingTooltipIndicators: [0, 1, 2], + barRods: [ + barChartRodData2, + barChartRodData3, + barChartRodData4, + barChartRodData1, + ], + barsSpace: 23, ); -const FlGridData flGridData3 = FlGridData( - verticalInterval: 12, - horizontalInterval: 43, - drawVerticalLine: false, - checkToShowVerticalLine: checkToShowLine, - getDrawingHorizontalLine: getDrawingLine, +final BarChartGroupData barChartGroupData7 = BarChartGroupData( + x: 12, + showingTooltipIndicators: [0, 1, 2], + barRods: [ + barChartRodData1, + barChartRodData2, + barChartRodData3, + barChartRodData4, + ], + barsSpace: 44, ); -const FlGridData flGridData4 = FlGridData( - verticalInterval: 12, - horizontalInterval: 22, - drawVerticalLine: false, - getDrawingHorizontalLine: getDrawingLine, +final BarChartGroupData barChartGroupData8 = BarChartGroupData( + x: 12, + barRods: [ + barChartRodData1, + barChartRodData2, + barChartRodData3, + barChartRodData4, + ], + barsSpace: 23, ); -const FlGridData flGridData5 = FlGridData( - verticalInterval: 12, - horizontalInterval: 22, - checkToShowVerticalLine: checkToShowLine, - getDrawingHorizontalLine: getDrawingLine, +final BarChartGroupData barChartGroupData9 = BarChartGroupData( + x: 12, + showingTooltipIndicators: [0, 1, 2], + barRods: [ + barChartRodData1, + barChartRodData2, + barChartRodData3, + barChartRodData4, + ], + barsSpace: 0, ); -final FlBorderData borderData1 = FlBorderData( - show: true, - border: Border.all(color: Colors.green), +final BarChartRodData barChartRodData1 = BarChartRodData( + color: Colors.red, + toY: 12, + width: 32, + borderRadius: const BorderRadius.all(Radius.circular(12)), + rodStackItems: [ + barChartRodStackItem1, + barChartRodStackItem2, + barChartRodStackItem3, + barChartRodStackItem4, + ], + backDrawRodData: backgroundBarChartRodData1, ); -final FlBorderData borderData1Clone = FlBorderData( - show: true, - border: Border.all(color: Colors.green), +final BarChartRodData barChartRodData1Clone = barChartRodData1.copyWith( + rodStackItems: [ + barChartRodStackItem1Clone, + barChartRodStackItem2, + barChartRodStackItem3, + barChartRodStackItem4, + ], ); -final FlBorderData borderData2 = FlBorderData( - show: true, - border: Border.all(color: Colors.green.withValues(alpha: 0.5)), + +final BarChartRodData barChartRodData2 = BarChartRodData( + color: Colors.red, + toY: 1132, + width: 32, + borderRadius: const BorderRadius.all(Radius.circular(12)), + rodStackItems: [ + barChartRodStackItem1, + barChartRodStackItem2, + barChartRodStackItem3, + barChartRodStackItem4, + ], + backDrawRodData: backgroundBarChartRodData1, +); +final BarChartRodData barChartRodData3 = BarChartRodData( + color: Colors.green, + toY: 12, + width: 32, + borderRadius: const BorderRadius.all(Radius.circular(12)), + rodStackItems: [ + barChartRodStackItem2, + ], + backDrawRodData: backgroundBarChartRodData1, +); +final BarChartRodData barChartRodData4 = BarChartRodData( + color: Colors.red, + toY: 12, + width: 32, + borderRadius: const BorderRadius.all(Radius.circular(12)), + rodStackItems: [ + barChartRodStackItem2, + barChartRodStackItem1, + barChartRodStackItem4, + barChartRodStackItem3, + ], + backDrawRodData: backgroundBarChartRodData1, ); -bool checkToShowSpotLine(FlSpot spot) => true; +final BarChartRodData barChartRodData5 = BarChartRodData( + color: Colors.red, + toY: 12, + width: 55, + borderRadius: const BorderRadius.all(Radius.circular(12)), + rodStackItems: [ + barChartRodStackItem1, + barChartRodStackItem2, + barChartRodStackItem4, + barChartRodStackItem3, + ], + backDrawRodData: backgroundBarChartRodData1, +); -const BarAreaSpotsLine barAreaSpotsLine1 = - BarAreaSpotsLine(show: true, checkToShowSpotLine: checkToShowSpotLine); -const BarAreaSpotsLine barAreaSpotsLine1Clone = - BarAreaSpotsLine(show: true, checkToShowSpotLine: checkToShowSpotLine); +final BarChartRodData barChartRodData6 = BarChartRodData( + color: Colors.red, + toY: 12, + width: 32, + borderRadius: const BorderRadius.all(Radius.circular(12)), + backDrawRodData: backgroundBarChartRodData1, +); -const BarAreaSpotsLine barAreaSpotsLine2 = BarAreaSpotsLine( - show: true, +final BarChartRodData barChartRodData7 = BarChartRodData( + color: Colors.red, + toY: 12, + width: 32, + borderRadius: const BorderRadius.all(Radius.circular(12)), + rodStackItems: [ + barChartRodStackItem1, + barChartRodStackItem2, + barChartRodStackItem4, + barChartRodStackItem3, + ], + backDrawRodData: backgroundBarChartRodData2, ); -final BarAreaData barAreaData1 = BarAreaData( - show: true, - cutOffY: 12, - gradient: const LinearGradient( - colors: [Colors.green, Colors.blue], - stops: [0, 0.5], - begin: Alignment.topLeft, - end: Alignment.bottomCenter, - ), - spotsLine: barAreaSpotsLine1, +final BarChartRodData barChartRodData8 = BarChartRodData( + color: Colors.red, + toY: 12, + width: 32, + borderRadius: const BorderRadius.all(Radius.circular(14)), + rodStackItems: [ + barChartRodStackItem1, + barChartRodStackItem2, + barChartRodStackItem4, + barChartRodStackItem3, + ], + backDrawRodData: backgroundBarChartRodData1, ); -final BarAreaData barAreaData1Clone = BarAreaData( - show: true, - cutOffY: 12, - gradient: const LinearGradient( - colors: [Colors.green, Colors.blue], - stops: [0, 0.5], - begin: Alignment.topLeft, - end: Alignment.bottomCenter, +final BarChartRodStackItem barChartRodStackItem1 = BarChartRodStackItem( + 1, + 2, + Colors.green, + label: 'Test Label', + labelStyle: const TextStyle( + color: Colors.white, + fontSize: 14, + fontWeight: FontWeight.bold, ), - spotsLine: barAreaSpotsLine1, ); -final BarAreaData barAreaData2 = BarAreaData( - show: true, - cutOffY: 12, - gradient: const LinearGradient( - colors: [Colors.green, Colors.blue], - stops: [0, 0.5], - begin: Alignment.topLeft, - end: Alignment.bottomCenter, - ), - spotsLine: barAreaSpotsLine2, +final BarChartRodStackItem barChartRodStackItem1Clone = + barChartRodStackItem1.copyWith(); +final BarChartRodStackItem barChartRodStackItem2 = BarChartRodStackItem( + 2, + 3, + Colors.green, ); -final BarAreaData barAreaData3 = BarAreaData( - show: true, - cutOffY: 12, - gradient: const LinearGradient( - colors: [Colors.green, Colors.blue], - stops: [0, 0.6], - begin: Alignment.topLeft, - end: Alignment.bottomCenter, - ), - spotsLine: barAreaSpotsLine2, +final BarChartRodStackItem barChartRodStackItem3 = BarChartRodStackItem( + 3, + 4, + Colors.green, + label: 'This is a very long label that might not fit', + labelStyle: const TextStyle(fontSize: 12), ); -final BarAreaData barAreaData4 = BarAreaData( - show: true, - cutOffY: 12, - gradient: const LinearGradient( - colors: [Colors.green, Colors.blue], - stops: [0], - begin: Alignment.topLeft, - end: Alignment.bottomCenter, - ), - spotsLine: barAreaSpotsLine2, +final BarChartRodStackItem barChartRodStackItem4 = BarChartRodStackItem( + 8, + 10, + Colors.purple, + label: 'Label with emojis 🎯 & symbols!', + labelStyle: const TextStyle(fontWeight: FontWeight.bold), ); - -bool checkToShowDot(FlSpot spot, LineChartBarData barData) => true; - -FlDotCirclePainter getDotDrawer( - FlSpot spot, - double percent, - LineChartBarData barData, - int index, -) => - FlDotCirclePainter(radius: 44, strokeWidth: 12); - -FlDotCirclePainter getDotDrawer5( - FlSpot spot, - double percent, - LineChartBarData barData, - int index, -) => - FlDotCirclePainter(radius: 44, strokeWidth: 14); - -FlDotCirclePainter getDotDrawer6( - FlSpot spot, - double percent, - LineChartBarData barData, - int index, -) => - FlDotCirclePainter(radius: 44.01, strokeWidth: 14); - -FlDotCirclePainter getDotDrawerTouched( - FlSpot spot, - double percent, - LineChartBarData barData, - int index, -) => - FlDotCirclePainter(radius: 12, color: Colors.red); - -FlDotCirclePainter getDotDrawerTouched4( - FlSpot spot, - double percent, - LineChartBarData barData, - int index, -) => - FlDotCirclePainter(radius: 12); - -FlDotCirclePainter getDotDrawerTouched6( - FlSpot spot, - double percent, - LineChartBarData barData, - int index, -) => - FlDotCirclePainter(radius: 12.01, color: Colors.red); - -const FlDotData flDotData1 = FlDotData( - getDotPainter: getDotDrawer, - checkToShowDot: checkToShowDot, +final BarTooltipItem barTooltipItem1 = BarTooltipItem( + 'pashmam 1', + const TextStyle(color: Colors.red), ); -const FlDotData flDotData1Clone = FlDotData( - getDotPainter: getDotDrawer, - checkToShowDot: checkToShowDot, +final BarTooltipItem barTooltipItem1Clone = BarTooltipItem( + 'pashmam 1', + const TextStyle(color: Colors.red), ); -const FlDotData flDotData4 = FlDotData( - getDotPainter: getDotDrawer, +final BarTooltipItem barTooltipItem2 = BarTooltipItem( + 'pashmam 2', + const TextStyle(color: Colors.red), ); -const FlDotData flDotData5 = FlDotData( - getDotPainter: getDotDrawer5, +final BarTooltipItem barTooltipItem3 = BarTooltipItem( + 'pashmam 1', + const TextStyle(color: Colors.green), ); -const FlDotData flDotData6 = FlDotData( - getDotPainter: getDotDrawer6, +final BarTooltipItem barTooltipItem4 = BarTooltipItem( + 'null', + const TextStyle(color: Colors.red), +); +final BarTooltipItem barTooltipItem5 = BarTooltipItem( + 'pashmam 1', + const TextStyle(fontSize: 85), ); -const Shadow shadow1 = Shadow( - color: Colors.red, - blurRadius: 12, -); -const Shadow shadow1Clone = Shadow( - color: Colors.red, - blurRadius: 12, +final BarTouchData barTouchData1 = BarTouchData( + touchTooltipData: barTouchTooltipData1, + handleBuiltInTouches: false, + touchCallback: barTouchCallback, + enabled: false, + allowTouchBarBackDraw: true, + touchExtraThreshold: const EdgeInsets.all(12), ); -const Shadow shadow2 = Shadow( - color: Colors.green, - blurRadius: 12, +final BarTouchData barTouchData10 = BarTouchData( + touchTooltipData: barTouchTooltipData1, + handleBuiltInTouches: false, + touchCallback: barTouchCallback, + enabled: false, + allowTouchBarBackDraw: true, + touchExtraThreshold: const EdgeInsets.all(12), + longPressDuration: Duration.zero, ); -const Shadow shadow3 = Shadow( - color: Colors.red, - blurRadius: 14, +final BarTouchData barTouchData1Clone = BarTouchData( + touchTooltipData: barTouchTooltipData1Clone, + handleBuiltInTouches: false, + touchCallback: barTouchCallback, + enabled: false, + allowTouchBarBackDraw: true, + touchExtraThreshold: const EdgeInsets.all(12), ); -final Shadow shadow4 = Shadow( - color: Colors.red.withValues(alpha: 0.5), - blurRadius: 12, +final BarTouchData barTouchData3 = BarTouchData( + touchTooltipData: barTouchTooltipData1, + handleBuiltInTouches: true, + touchCallback: barTouchCallback, + enabled: false, + allowTouchBarBackDraw: true, + touchExtraThreshold: const EdgeInsets.all(12), ); - -const LineChartStepData lineChartStepData1 = LineChartStepData(); - -const LineChartStepData lineChartStepData1Clone = LineChartStepData(); - -const LineChartStepData lineChartStepData2 = LineChartStepData( - stepDirection: LineChartStepData.stepDirectionForward, +final BarTouchData barTouchData4 = BarTouchData( + touchTooltipData: barTouchTooltipData2, + handleBuiltInTouches: false, + touchCallback: barTouchCallback, + enabled: false, + allowTouchBarBackDraw: true, + touchExtraThreshold: const EdgeInsets.all(12), ); - -final LineChartBarData lineChartBarData1 = LineChartBarData( - dashArray: [0, 1], - gradient: const LinearGradient( - colors: [Colors.red, Colors.green], - stops: [0, 1], - begin: Alignment.center, - end: Alignment.bottomRight, - ), - spots: [ - flSpot1, - flSpot2, - ], - shadow: shadow1, - aboveBarData: barAreaData1, - belowBarData: barAreaData2, - barWidth: 12, - curveSmoothness: 12, - dotData: flDotData1, - isStrokeCapRound: true, - preventCurveOvershootingThreshold: 1.2, - showingIndicators: [0, 1], - errorIndicatorData: const FlErrorIndicatorData( - show: false, - ), +final BarTouchData barTouchData5 = BarTouchData( + touchTooltipData: barTouchTooltipData1, + handleBuiltInTouches: false, + enabled: false, + allowTouchBarBackDraw: true, + touchExtraThreshold: const EdgeInsets.all(12), ); -final LineChartBarData lineChartBarData1Clone = LineChartBarData( - dashArray: [0, 1], - gradient: const LinearGradient( - colors: [Colors.red, Colors.green], - stops: [0, 1], - begin: Alignment.center, - end: Alignment.bottomRight, - ), - spots: [ - flSpot1Clone, - flSpot2, - ], - shadow: shadow1Clone, - aboveBarData: barAreaData1Clone, - belowBarData: barAreaData2, - barWidth: 12, - curveSmoothness: 12, - dotData: flDotData1Clone, - isStrokeCapRound: true, - preventCurveOvershootingThreshold: 1.2, - showingIndicators: [0, 1], - errorIndicatorData: const FlErrorIndicatorData( - show: false, - ), +final BarTouchData barTouchData6 = BarTouchData( + touchTooltipData: barTouchTooltipData1, + handleBuiltInTouches: false, + touchCallback: barTouchCallback, + enabled: true, + allowTouchBarBackDraw: true, + touchExtraThreshold: const EdgeInsets.all(12), ); -final LineChartBarData lineChartBarData2 = LineChartBarData( - dashArray: [0, 1], - gradient: const LinearGradient( - colors: [Colors.red, Colors.green], - stops: [0, 1], - begin: Alignment.center, - end: Alignment.bottomRight, - ), - spots: [ - flSpot1, - flSpot2, - ], - shadow: shadow2, - isStepLineChart: true, - aboveBarData: barAreaData1, - belowBarData: barAreaData2, - barWidth: 12, - curveSmoothness: 12, - dotData: flDotData1, - isStrokeCapRound: true, - preventCurveOvershootingThreshold: 1.2, - showingIndicators: [0, 4], +final BarTouchData barTouchData7 = BarTouchData( + touchTooltipData: barTouchTooltipData1, + handleBuiltInTouches: false, + touchCallback: barTouchCallback, + enabled: false, + allowTouchBarBackDraw: false, + touchExtraThreshold: const EdgeInsets.all(12), ); -final LineChartBarData lineChartBarData3 = LineChartBarData( - gradient: const LinearGradient( - colors: [Colors.red, Colors.green], - stops: [0, 1], - begin: Alignment.center, - end: Alignment.bottomRight, - ), - spots: [ - flSpot1, - flSpot2, - ], - shadow: shadow3, - isStepLineChart: true, - lineChartStepData: lineChartStepData2, - aboveBarData: barAreaData1, - belowBarData: barAreaData2, - barWidth: 12, - curveSmoothness: 12, - dotData: flDotData1, - isStrokeCapRound: true, - preventCurveOvershootingThreshold: 1.2, - showingIndicators: [0, 1], +final BarTouchData barTouchData8 = BarTouchData( + touchTooltipData: barTouchTooltipData1, + handleBuiltInTouches: false, + touchCallback: barTouchCallback, + enabled: false, + allowTouchBarBackDraw: true, ); -final LineChartBarData lineChartBarData4 = LineChartBarData( - dashArray: [0, 1], - gradient: const LinearGradient( - colors: [Colors.red, Colors.green], - stops: [0, 1], - begin: Alignment.center, - end: Alignment.bottomRight, - ), - spots: [ - flSpot2, - flSpot1, - ], - shadow: shadow4, - lineChartStepData: lineChartStepData2, - aboveBarData: barAreaData1, - belowBarData: barAreaData2, - barWidth: 12, - curveSmoothness: 12, - dotData: flDotData1, - isStrokeCapRound: true, - preventCurveOvershootingThreshold: 1.2, - showingIndicators: [0, 1], +final BarTouchData barTouchData9 = BarTouchData( + touchTooltipData: barTouchTooltipData1, + handleBuiltInTouches: false, + touchCallback: barTouchCallback, + enabled: false, + allowTouchBarBackDraw: true, + touchExtraThreshold: const EdgeInsets.only(left: 12), ); - -final LineChartBarData lineChartBarData5 = LineChartBarData( - dashArray: [0, 1], - gradient: const LinearGradient( - colors: [Colors.red, Colors.green], - stops: [0, 1], - begin: Alignment.center, - end: Alignment.bottomRight, - ), - spots: [ - flSpot1, - flSpot2, - ], - aboveBarData: barAreaData2, - belowBarData: barAreaData1, - barWidth: 12, - curveSmoothness: 12, - dotData: flDotData1, - isStrokeCapRound: true, - preventCurveOvershootingThreshold: 1.2, - showingIndicators: [0, 1], +final BarTouchedSpot barTouchedSpot1 = BarTouchedSpot( + barChartGroupData1, + 1, + barChartRodData1, + 2, + barChartRodStackItem1, + 1, + flSpot1, + Offset.zero, ); - -final LineChartBarData lineChartBarData6 = LineChartBarData( - dashArray: [0, 1], - gradient: const LinearGradient( - colors: [Colors.red, Colors.green], - stops: [0, 1], - begin: Alignment.center, - end: Alignment.bottomRight, - ), - spots: [ - flSpot1, - flSpot2, - ], - aboveBarData: barAreaData1, - belowBarData: barAreaData2, - barWidth: 12, - curveSmoothness: 12, - dotData: flDotData1, - isStrokeCapRound: true, - preventCurveOvershootingThreshold: 1.2, - showingIndicators: [0, 1], -); - -final LineChartBarData lineChartBarData7 = LineChartBarData( - dashArray: [0, 1], - gradient: LinearGradient( - colors: [Colors.red, Colors.green.withValues(alpha: 0.4)], - stops: const [0, 1], - begin: Alignment.center, - end: Alignment.bottomRight, - ), - spots: [ - flSpot1, - flSpot2, - ], - aboveBarData: barAreaData1, - belowBarData: barAreaData2, - barWidth: 12, - curveSmoothness: 12, - dotData: flDotData1, - isStrokeCapRound: true, - preventCurveOvershootingThreshold: 1.2, - showingIndicators: [0, 1], -); - -final LineChartBarData lineChartBarData8 = LineChartBarData( - dashArray: [0, 1], - gradient: const LinearGradient( - colors: [Colors.red, Colors.green], - stops: [0, 1], - begin: Alignment.center, - end: Alignment.bottomRight, - ), - spots: [ - flSpot1, - flSpot2, - ], - aboveBarData: barAreaData1, - belowBarData: barAreaData2, - barWidth: 12, - curveSmoothness: 12.01, - dotData: flDotData1, - isStrokeCapRound: true, - preventCurveOvershootingThreshold: 1.2, - showingIndicators: [0, 1], +final BarTouchedSpot barTouchedSpot1Clone = BarTouchedSpot( + barChartGroupData1Clone, + 1, + barChartRodData1Clone, + 2, + barChartRodStackItem1Clone, + 1, + flSpot1Clone, + Offset.zero, ); - -final LineChartBarData lineChartBarData9 = LineChartBarData( - dashArray: [0, 1], - gradient: const LinearGradient( - colors: [Colors.red, Colors.green], - stops: [0, 1], - begin: Alignment.center, - end: Alignment.bottomRight, - ), - spots: [ - flSpot1, - flSpot2, - ], - aboveBarData: barAreaData1, - belowBarData: barAreaData2, - barWidth: 12, - curveSmoothness: 12, - dotData: flDotData1, - isStrokeCapRound: true, - preventCurveOverShooting: true, - preventCurveOvershootingThreshold: 1.2, - showingIndicators: [0, 1], +final BarTouchedSpot barTouchedSpot2 = BarTouchedSpot( + barChartGroupData2, + 1, + barChartRodData1, + 2, + barChartRodStackItem2, + 2, + flSpot1, + Offset.zero, ); - -final TouchLineBarSpot lineBarSpot1 = TouchLineBarSpot( - lineChartBarData1, - 0, +final BarTouchedSpot barTouchedSpot3 = BarTouchedSpot( + barChartGroupData1, + 1, + barChartRodData2, + 2, + barChartRodStackItem2, + 2, flSpot1, - 0, + Offset.zero, ); -final TouchLineBarSpot lineBarSpot1Clone = TouchLineBarSpot( - lineChartBarData1Clone, - 0, - flSpot1Clone, - 0, +final BarTouchedSpot barTouchedSpot4 = BarTouchedSpot( + barChartGroupData1, + 2, + barChartRodData1, + 2, + barChartRodStackItem2, + 2, + flSpot1, + Offset.zero, ); - -final TouchLineBarSpot lineBarSpot2 = - TouchLineBarSpot(lineChartBarData1, 2, flSpot1, 2); - -final TouchLineBarSpot lineBarSpot3 = TouchLineBarSpot( - lineChartBarData1, - 100, +final BarTouchedSpot barTouchedSpot5 = BarTouchedSpot( + barChartGroupData1, + 1, + barChartRodData1, + 3, + barChartRodStackItem2, + 2, flSpot1, + Offset.zero, +); +final BarTouchedSpot barTouchedSpot6 = BarTouchedSpot( + barChartGroupData1, + 1, + barChartRodData1, + 2, + barChartRodStackItem2, 2, + flSpot2, + Offset.zero, ); -final lineTouchResponse1 = LineTouchResponse( - touchLocation: Offset.zero, - touchChartCoordinate: Offset.zero, - lineBarSpots: [ - lineBarSpot1, - lineBarSpot2, - ], +final BarTouchedSpot barTouchedSpot7 = BarTouchedSpot( + barChartGroupData1, + 1, + barChartRodData1, + 2, + barChartRodStackItem2, + 2, + flSpot1, + const Offset(1, 10), ); -final lineTouchResponse1Clone = LineTouchResponse( +final barTouchResponse1 = BarTouchResponse( touchLocation: Offset.zero, touchChartCoordinate: Offset.zero, - lineBarSpots: [ - lineBarSpot1Clone, - lineBarSpot2, - ], + spot: barTouchedSpot1, ); - -final lineTouchResponse2 = LineTouchResponse( +final barTouchResponse1Clone = BarTouchResponse( touchLocation: Offset.zero, touchChartCoordinate: Offset.zero, - lineBarSpots: [ - lineBarSpot2, - lineBarSpot1, - ], + spot: barTouchedSpot1Clone, ); - -final lineTouchResponse3 = LineTouchResponse( +final barTouchResponse2 = BarTouchResponse( touchLocation: Offset.zero, touchChartCoordinate: Offset.zero, - lineBarSpots: [], + spot: barTouchedSpot2, ); - -final lineTouchResponse4 = LineTouchResponse( - touchLocation: Offset.zero, - touchChartCoordinate: Offset.zero, - lineBarSpots: [ - lineBarSpot1, - lineBarSpot2, - ], +final BarTouchTooltipData barTouchTooltipData1 = BarTouchTooltipData( + tooltipBorderRadius: BorderRadius.circular(12), + fitInsideVertically: false, + fitInsideHorizontally: true, + maxContentWidth: 23, + getTooltipColor: getTooltipGreenColor, + tooltipPadding: const EdgeInsets.all(23), + getTooltipItem: getTooltipItem, + tooltipMargin: 12, + tooltipBorder: const BorderSide(color: Colors.red), ); - -final lineTouchResponse5 = LineTouchResponse( - touchLocation: Offset.zero, - touchChartCoordinate: Offset.zero, - lineBarSpots: [ - lineBarSpot1, - lineBarSpot2, - ], +final BarTouchTooltipData barTouchTooltipData10 = BarTouchTooltipData( + tooltipBorderRadius: BorderRadius.circular(12), + fitInsideVertically: false, + fitInsideHorizontally: true, + maxContentWidth: 23, + getTooltipColor: getTooltipGreenColor, + tooltipPadding: const EdgeInsets.all(23), + getTooltipItem: getTooltipItem, + tooltipMargin: 12, + tooltipBorder: const BorderSide(color: Colors.blue), ); - -const TouchedSpotIndicatorData touchedSpotIndicatorData1 = - TouchedSpotIndicatorData( - FlLine( - color: Colors.red, - dashArray: [], - ), - FlDotData( - getDotPainter: getDotDrawerTouched, - checkToShowDot: checkToShowDot, - ), +final BarTouchTooltipData barTouchTooltipData11 = BarTouchTooltipData( + tooltipBorderRadius: BorderRadius.circular(12), + fitInsideVertically: false, + fitInsideHorizontally: true, + maxContentWidth: 23, + getTooltipColor: getTooltipGreenColor, + tooltipPadding: const EdgeInsets.all(23), + getTooltipItem: getTooltipItem, + tooltipMargin: 12, + tooltipBorder: const BorderSide(color: Colors.red, width: 2), ); -const TouchedSpotIndicatorData touchedSpotIndicatorData1Clone = - TouchedSpotIndicatorData( - FlLine( - color: Colors.red, - dashArray: [], - ), - FlDotData( - getDotPainter: getDotDrawerTouched, - checkToShowDot: checkToShowDot, - ), +final BarTouchTooltipData barTouchTooltipData1Clone = BarTouchTooltipData( + tooltipBorderRadius: BorderRadius.circular(12), + fitInsideVertically: false, + fitInsideHorizontally: true, + maxContentWidth: 23, + getTooltipColor: getTooltipGreenColor, + tooltipPadding: const EdgeInsets.all(23), + getTooltipItem: getTooltipItem, + tooltipMargin: 12, + tooltipBorder: const BorderSide(color: Colors.red), ); -const TouchedSpotIndicatorData touchedSpotIndicatorData2 = - TouchedSpotIndicatorData( - FlLine( - color: Colors.red, - dashArray: [], - ), - FlDotData( - getDotPainter: getDotDrawerTouched, - ), -); -const TouchedSpotIndicatorData touchedSpotIndicatorData3 = - TouchedSpotIndicatorData( - FlLine( - color: Colors.red, - ), - FlDotData( - getDotPainter: getDotDrawerTouched, - checkToShowDot: checkToShowDot, - ), -); -const TouchedSpotIndicatorData touchedSpotIndicatorData4 = - TouchedSpotIndicatorData( - FlLine( - color: Colors.green, - dashArray: [], - ), - FlDotData( - getDotPainter: getDotDrawerTouched4, - checkToShowDot: checkToShowDot, - ), -); -const TouchedSpotIndicatorData touchedSpotIndicatorData5 = - TouchedSpotIndicatorData( - FlLine( - color: Colors.red, - dashArray: [], - ), - FlDotData( - getDotPainter: getDotDrawerTouched, - checkToShowDot: checkToShowDot, - show: false, - ), -); -const TouchedSpotIndicatorData touchedSpotIndicatorData6 = - TouchedSpotIndicatorData( - FlLine( - color: Colors.red, - dashArray: [], - ), - FlDotData( - getDotPainter: getDotDrawerTouched6, - checkToShowDot: checkToShowDot, - ), -); - -const LineTooltipItem lineTooltipItem1 = - LineTooltipItem('', TextStyle(color: Colors.green)); -const LineTooltipItem lineTooltipItem1Clone = - LineTooltipItem('', TextStyle(color: Colors.green)); - -const LineTooltipItem lineTooltipItem2 = - LineTooltipItem('ss', TextStyle(color: Colors.green)); -const LineTooltipItem lineTooltipItem3 = - LineTooltipItem('', TextStyle(color: Colors.blue)); -const LineTooltipItem lineTooltipItem4 = - LineTooltipItem('', TextStyle(fontSize: 33)); - -List lineChartGetTooltipItems(List list) { - return list.map((s) => lineTooltipItem1).toList(); -} - -Color lineChartGetGreenColor(LineBarSpot touchedSpot) { - return Colors.green; -} - -Color lineChartGetRedColor(LineBarSpot touchedSpot) { - return Colors.red; -} - -final LineTouchTooltipData lineTouchTooltipData1 = LineTouchTooltipData( - tooltipPadding: const EdgeInsets.all(0.1), - getTooltipColor: lineChartGetGreenColor, - maxContentWidth: 12, - getTooltipItems: lineChartGetTooltipItems, - fitInsideHorizontally: true, - tooltipBorderRadius: BorderRadius.circular(12), - tooltipMargin: 33, - tooltipBorder: const BorderSide(color: Colors.red), -); -final LineTouchTooltipData lineTouchTooltipData1Clone = LineTouchTooltipData( - tooltipPadding: const EdgeInsets.all(0.1), - getTooltipColor: lineChartGetGreenColor, - maxContentWidth: 12, - getTooltipItems: lineChartGetTooltipItems, +final BarTouchTooltipData barTouchTooltipData2 = BarTouchTooltipData( + tooltipBorderRadius: BorderRadius.circular(13), + fitInsideVertically: false, fitInsideHorizontally: true, - tooltipBorderRadius: BorderRadius.circular(12), - tooltipMargin: 33, + maxContentWidth: 23, + getTooltipColor: getTooltipGreenColor, + tooltipPadding: const EdgeInsets.all(23), + getTooltipItem: getTooltipItem, + tooltipMargin: 12, tooltipBorder: const BorderSide(color: Colors.red), + tooltipHorizontalAlignment: FLHorizontalAlignment.center, ); - -final LineTouchTooltipData lineTouchTooltipData2 = LineTouchTooltipData( - tooltipPadding: const EdgeInsets.all(0.1), - getTooltipColor: lineChartGetRedColor, - maxContentWidth: 12, - getTooltipItems: lineChartGetTooltipItems, - fitInsideHorizontally: true, +final BarTouchTooltipData barTouchTooltipData3 = BarTouchTooltipData( tooltipBorderRadius: BorderRadius.circular(12), - tooltipMargin: 33, - tooltipBorder: const BorderSide(color: Colors.red), -); -final LineTouchTooltipData lineTouchTooltipData3 = LineTouchTooltipData( - tooltipPadding: const EdgeInsets.all(0.2), - getTooltipColor: lineChartGetGreenColor, - maxContentWidth: 12, - getTooltipItems: lineChartGetTooltipItems, + fitInsideVertically: true, fitInsideHorizontally: true, - tooltipBorderRadius: BorderRadius.circular(12), - tooltipMargin: 33, + maxContentWidth: 23, + getTooltipColor: getTooltipGreenColor, + tooltipPadding: const EdgeInsets.all(23), + getTooltipItem: getTooltipItem, + tooltipMargin: 12, tooltipBorder: const BorderSide(color: Colors.red), tooltipHorizontalAlignment: FLHorizontalAlignment.left, ); -final LineTouchTooltipData lineTouchTooltipData4 = LineTouchTooltipData( - tooltipPadding: const EdgeInsets.all(0.1), - getTooltipColor: lineChartGetGreenColor, - maxContentWidth: 13, - getTooltipItems: lineChartGetTooltipItems, - fitInsideHorizontally: true, +final BarTouchTooltipData barTouchTooltipData4 = BarTouchTooltipData( tooltipBorderRadius: BorderRadius.circular(12), - tooltipMargin: 33, + fitInsideVertically: false, + fitInsideHorizontally: false, + maxContentWidth: 23, + getTooltipColor: getTooltipGreenColor, + tooltipPadding: const EdgeInsets.all(23), + getTooltipItem: getTooltipItem, + tooltipMargin: 12, tooltipBorder: const BorderSide(color: Colors.red), tooltipHorizontalAlignment: FLHorizontalAlignment.right, ); -final LineTouchTooltipData lineTouchTooltipData5 = LineTouchTooltipData( - tooltipPadding: const EdgeInsets.all(0.1), - getTooltipColor: lineChartGetGreenColor, - maxContentWidth: 12, - getTooltipItems: lineChartGetTooltipItems, - fitInsideHorizontally: true, +final BarTouchTooltipData barTouchTooltipData5 = BarTouchTooltipData( tooltipBorderRadius: BorderRadius.circular(12), - tooltipMargin: 34, + fitInsideVertically: false, + fitInsideHorizontally: true, + maxContentWidth: 23.00001, + getTooltipColor: getTooltipGreenColor, + tooltipPadding: const EdgeInsets.all(23), + getTooltipItem: getTooltipItem, + tooltipMargin: 12, tooltipBorder: const BorderSide(color: Colors.red), + tooltipHorizontalAlignment: FLHorizontalAlignment.center, tooltipHorizontalOffset: 10, ); -final LineTouchTooltipData lineTouchTooltipData6 = LineTouchTooltipData( - tooltipPadding: const EdgeInsets.all(0.1), - getTooltipColor: lineChartGetGreenColor, - maxContentWidth: 12, - getTooltipItems: lineChartGetTooltipItems, - fitInsideHorizontally: true, +final BarTouchTooltipData barTouchTooltipData6 = BarTouchTooltipData( tooltipBorderRadius: BorderRadius.circular(12), - tooltipMargin: 33, - tooltipBorder: const BorderSide(color: Colors.pink), + fitInsideVertically: false, + fitInsideHorizontally: true, + maxContentWidth: 23, + getTooltipColor: getTooltipBlueColor, + tooltipPadding: const EdgeInsets.all(23), + getTooltipItem: getTooltipItem, + tooltipMargin: 12, + tooltipBorder: const BorderSide(color: Colors.red), tooltipHorizontalAlignment: FLHorizontalAlignment.left, tooltipHorizontalOffset: -10, ); -final LineTouchTooltipData lineTouchTooltipData7 = LineTouchTooltipData( - tooltipPadding: const EdgeInsets.all(0.1), - getTooltipColor: lineChartGetGreenColor, - maxContentWidth: 12, - getTooltipItems: lineChartGetTooltipItems, - fitInsideHorizontally: true, +final BarTouchTooltipData barTouchTooltipData7 = BarTouchTooltipData( tooltipBorderRadius: BorderRadius.circular(12), - tooltipMargin: 33, - tooltipBorder: const BorderSide(color: Colors.red, width: 2), + fitInsideVertically: false, + fitInsideHorizontally: true, + maxContentWidth: 23, + getTooltipColor: getTooltipGreenColor, + getTooltipItem: getTooltipItem, + tooltipMargin: 12, + tooltipBorder: const BorderSide(color: Colors.red), tooltipHorizontalAlignment: FLHorizontalAlignment.right, tooltipHorizontalOffset: 10, ); - -void lineTouchCallback(FlTouchEvent event, LineTouchResponse? response) {} - -List getTouchedSpotIndicator( - LineChartBarData barData, - List indexes, -) => - indexes.map((i) => touchedSpotIndicatorData1).toList(); - -final LineTouchData lineTouchData1 = LineTouchData( - touchCallback: lineTouchCallback, - getTouchedSpotIndicator: getTouchedSpotIndicator, - handleBuiltInTouches: false, - touchSpotThreshold: 12, - touchTooltipData: lineTouchTooltipData1, +final BarTouchTooltipData barTouchTooltipData8 = BarTouchTooltipData( + tooltipBorderRadius: BorderRadius.circular(12), + fitInsideVertically: false, + fitInsideHorizontally: true, + maxContentWidth: 23, + getTooltipColor: getTooltipGreenColor, + tooltipPadding: const EdgeInsets.all(23), + tooltipMargin: 12, + tooltipBorder: const BorderSide(color: Colors.red), ); -final LineTouchData lineTouchData1Clone = LineTouchData( - touchCallback: lineTouchCallback, - getTouchedSpotIndicator: getTouchedSpotIndicator, - handleBuiltInTouches: false, - touchSpotThreshold: 12, - touchTooltipData: lineTouchTooltipData1, +final BarTouchTooltipData barTouchTooltipData9 = BarTouchTooltipData( + tooltipBorderRadius: BorderRadius.circular(12), + fitInsideVertically: false, + fitInsideHorizontally: true, + maxContentWidth: 23, + getTooltipColor: getTooltipGreenColor, + tooltipPadding: const EdgeInsets.all(23), + getTooltipItem: getTooltipItem, + tooltipMargin: 333, + tooltipBorder: const BorderSide(color: Colors.red), ); - -final LineTouchData lineTouchData2 = LineTouchData( - getTouchedSpotIndicator: getTouchedSpotIndicator, - handleBuiltInTouches: false, - touchSpotThreshold: 12, - touchTooltipData: lineTouchTooltipData1, +final BetweenBarsData betweenBarsData1 = BetweenBarsData( + fromIndex: 1, + toIndex: 2, + gradient: const LinearGradient( + begin: Alignment(1, 3), + end: Alignment(4, 1), + stops: [1, 2, 3], + colors: [Colors.green, Colors.blue, Colors.red], + ), ); -final LineTouchData lineTouchData3 = LineTouchData( - touchCallback: lineTouchCallback, - handleBuiltInTouches: false, - touchSpotThreshold: 12, - touchTooltipData: lineTouchTooltipData1, +final BetweenBarsData betweenBarsData1Clone = BetweenBarsData( + fromIndex: 1, + toIndex: 2, + gradient: const LinearGradient( + begin: Alignment(1, 3), + end: Alignment(4, 1), + stops: [1, 2, 3], + colors: [Colors.green, Colors.blue, Colors.red], + ), ); -const LineTouchData lineTouchData4 = LineTouchData( - touchCallback: lineTouchCallback, - getTouchedSpotIndicator: getTouchedSpotIndicator, - handleBuiltInTouches: false, - touchSpotThreshold: 12, -); -final LineTouchData lineTouchData5 = LineTouchData( - touchCallback: lineTouchCallback, - getTouchedSpotIndicator: getTouchedSpotIndicator, - handleBuiltInTouches: false, - touchSpotThreshold: 12.001, - touchTooltipData: lineTouchTooltipData1, -); -final LineTouchData lineTouchData6 = LineTouchData( - touchCallback: lineTouchCallback, - getTouchedSpotIndicator: getTouchedSpotIndicator, - touchSpotThreshold: 12, - touchTooltipData: lineTouchTooltipData1, + +final BetweenBarsData betweenBarsData2 = BetweenBarsData( + fromIndex: 2, + toIndex: 2, + gradient: const LinearGradient( + begin: Alignment(1, 3), + end: Alignment(4, 1), + stops: [1, 2, 3], + colors: [Colors.green, Colors.blue, Colors.red], + ), ); -final LineTouchData lineTouchData7 = LineTouchData( - touchCallback: lineTouchCallback, - getTouchedSpotIndicator: getTouchedSpotIndicator, - handleBuiltInTouches: false, - touchSpotThreshold: 12, - touchTooltipData: lineTouchTooltipData1, - getTouchLineEnd: (barData, index) => double.infinity, +final BetweenBarsData betweenBarsData3 = BetweenBarsData( + fromIndex: 1, + toIndex: 1, + gradient: const LinearGradient( + begin: Alignment(1, 4), + end: Alignment(4, 1), + stops: [1, 2, 3], + colors: [Colors.green, Colors.blue, Colors.red], + ), ); -final LineTouchData lineTouchData8 = LineTouchData( - touchCallback: lineTouchCallback, - getTouchedSpotIndicator: getTouchedSpotIndicator, - handleBuiltInTouches: false, - touchSpotThreshold: 12, - touchTooltipData: lineTouchTooltipData1, - longPressDuration: Duration.zero, +final BetweenBarsData betweenBarsData4 = BetweenBarsData( + fromIndex: 1, + toIndex: 2, + gradient: const LinearGradient( + begin: Alignment(1, 3), + end: Alignment(5, 1), + stops: [1, 2, 3], + colors: [Colors.green, Colors.blue, Colors.red], + ), ); - -String horizontalLabelResolver(HorizontalLine horizontalLine) => 'test'; - -String verticalLabelResolver(VerticalLine horizontalLine) => 'test'; - -final HorizontalLineLabel horizontalLineLabel1 = HorizontalLineLabel( - show: true, - style: const TextStyle(color: Colors.green), - labelResolver: horizontalLabelResolver, - alignment: Alignment.topCenter, - padding: const EdgeInsets.all(12), - direction: LabelDirection.vertical, +final BetweenBarsData betweenBarsData5 = BetweenBarsData( + fromIndex: 1, + toIndex: 2, + gradient: const LinearGradient( + begin: Alignment(1, 3), + end: Alignment(4, 1), + colors: [Colors.green, Colors.blue, Colors.red], + ), ); -final HorizontalLineLabel horizontalLineLabel1Clone = HorizontalLineLabel( - show: true, - style: const TextStyle(color: Colors.green), - labelResolver: horizontalLabelResolver, - alignment: Alignment.topCenter, - padding: const EdgeInsets.all(12), - direction: LabelDirection.vertical, +final BetweenBarsData betweenBarsData6 = BetweenBarsData( + fromIndex: 1, + toIndex: 2, + gradient: const LinearGradient( + begin: Alignment(1, 3), + end: Alignment(4, 1), + stops: [1, 2, 3], + colors: [Colors.green, Colors.blue], + ), ); -final HorizontalLineLabel horizontalLineLabel2 = HorizontalLineLabel( - style: const TextStyle(color: Colors.green), - labelResolver: horizontalLabelResolver, - alignment: Alignment.topCenter, - padding: const EdgeInsets.all(12), +final BetweenBarsData betweenBarsData7 = BetweenBarsData( + fromIndex: 1, + toIndex: 2, + gradient: const LinearGradient( + begin: Alignment(1, 22), + end: Alignment(4, 1), + stops: [1, 2, 3], + colors: [Colors.green, Colors.blue], + ), ); -final HorizontalLineLabel horizontalLineLabel3 = HorizontalLineLabel( - show: true, - labelResolver: horizontalLabelResolver, - alignment: Alignment.topCenter, - padding: const EdgeInsets.all(12), +final BetweenBarsData betweenBarsData8 = BetweenBarsData( + fromIndex: 1, + toIndex: 2, + gradient: const LinearGradient( + begin: Alignment(1, 3), + end: Alignment(4, 1), + stops: [1, 2, 3], + colors: [], + ), ); -final HorizontalLineLabel horizontalLineLabel4 = HorizontalLineLabel( +final FlBorderData borderData1 = FlBorderData( show: true, - style: const TextStyle(color: Colors.green), - alignment: Alignment.topCenter, - padding: const EdgeInsets.all(12), + border: Border.all(color: Colors.green), ); -final HorizontalLineLabel horizontalLineLabel5 = HorizontalLineLabel( +final FlBorderData borderData1Clone = FlBorderData( show: true, - style: const TextStyle(color: Colors.green), - labelResolver: horizontalLabelResolver, - alignment: Alignment.bottomRight, - padding: const EdgeInsets.all(12), + border: Border.all(color: Colors.green), ); -final HorizontalLineLabel horizontalLineLabel6 = HorizontalLineLabel( +final FlBorderData borderData2 = FlBorderData( show: true, - style: const TextStyle(color: Colors.green), - labelResolver: horizontalLabelResolver, - alignment: Alignment.topCenter, - padding: const EdgeInsets.all(44), + border: Border.all(color: Colors.green.withValues(alpha: 0.5)), ); -final HorizontalLineLabel horizontalLineLabel7 = HorizontalLineLabel( - style: const TextStyle(color: Colors.green), - labelResolver: horizontalLabelResolver, - alignment: Alignment.topCenter, - padding: const EdgeInsets.all(12), - direction: LabelDirection.vertical, + +final candleStickChartData1 = CandlestickChartData( + candlestickSpots: [ + candlestickSpot1, + candlestickSpot2, + candlestickSpot3, + candlestickSpot4, + ], + candlestickPainter: DefaultCandlestickPainter(), + titlesData: MockData.flTitlesData1, + candlestickTouchData: candlestickTouchData1, + showingTooltipIndicators: [0, 1, 2], + gridData: flGridData1, + borderData: borderData1, + minX: 0, + maxX: 1000, + minY: 0, + maxY: 1000, + baselineX: 0, + baselineY: 0, + backgroundColor: Colors.white, + rangeAnnotations: rangeAnnotations1, + clipData: const FlClipData.none(), ); +final CandlestickChartData candleStickChartData1Clone = + candleStickChartData1.copyWith(); -final VerticalLineLabel verticalLineLabel1 = VerticalLineLabel( - show: true, - style: const TextStyle(color: Colors.green), - labelResolver: verticalLabelResolver, - alignment: Alignment.topCenter, - padding: const EdgeInsets.all(12), +final candleStickChartData2 = CandlestickChartData( + candlestickSpots: [ + candlestickSpot1, + candlestickSpot2, + candlestickSpot3, + candlestickSpot4, + ], + candlestickPainter: DefaultCandlestickPainter(), + titlesData: MockData.flTitlesData2, + candlestickTouchData: candlestickTouchData1, + showingTooltipIndicators: [1, 2, 3], + gridData: flGridData1, + borderData: borderData1, + minX: 0, + maxX: 1000, + minY: 0, + maxY: 1000, + baselineX: 0, + baselineY: 0, + backgroundColor: Colors.white, + rangeAnnotations: rangeAnnotations1, + clipData: const FlClipData.all(), + rotationQuarterTurns: 1, ); -final VerticalLineLabel verticalLineLabel1Clone = VerticalLineLabel( - show: true, - style: const TextStyle(color: Colors.green), - labelResolver: verticalLabelResolver, - alignment: Alignment.topCenter, - padding: const EdgeInsets.all(12), +final candlestickSpot1 = CandlestickSpot( + x: 0, + open: 10, + high: 100, + low: 0, + close: 20, ); -final VerticalLineLabel verticalLineLabel2 = VerticalLineLabel( - style: const TextStyle(color: Colors.green), - labelResolver: verticalLabelResolver, - alignment: Alignment.topCenter, - padding: const EdgeInsets.all(12), +final CandlestickSpot candlestickSpot1Clone = candlestickSpot1.copyWith(); +final candlestickSpot2 = CandlestickSpot( + x: 10, + open: 30, + high: 110, + low: 10, + close: 20, ); -final VerticalLineLabel verticalLineLabel3 = VerticalLineLabel( - show: true, - labelResolver: verticalLabelResolver, - alignment: Alignment.topCenter, - padding: const EdgeInsets.all(12), +final CandlestickSpot candlestickSpot2Clone = candlestickSpot2.copyWith(); + +final candlestickSpot3 = CandlestickSpot( + x: 20, + open: 30, + high: 120, + low: 20, + close: 40, ); -final VerticalLineLabel verticalLineLabel4 = VerticalLineLabel( - show: true, - style: const TextStyle(color: Colors.green), - alignment: Alignment.topCenter, - padding: const EdgeInsets.all(12), -); -final VerticalLineLabel verticalLineLabel5 = VerticalLineLabel( - show: true, - style: const TextStyle(color: Colors.green), - labelResolver: verticalLabelResolver, - padding: const EdgeInsets.all(12), -); -final VerticalLineLabel verticalLineLabel6 = VerticalLineLabel( - show: true, - style: const TextStyle(color: Colors.green), - labelResolver: verticalLabelResolver, - alignment: Alignment.topCenter, - padding: const EdgeInsets.all(44), -); -final VerticalLineLabel verticalLineLabel7 = VerticalLineLabel( - style: const TextStyle(color: Colors.green), - labelResolver: verticalLabelResolver, - alignment: Alignment.topCenter, - padding: const EdgeInsets.all(12), - direction: LabelDirection.vertical, +final candlestickSpot4 = CandlestickSpot( + x: 30, + open: 40, + high: 130, + low: 30, + close: 50, ); -final HorizontalLine horizontalLine1 = HorizontalLine( - y: 12, - color: Colors.red, - dashArray: [0, 1], - strokeWidth: 21, - label: horizontalLineLabel1, -); -final HorizontalLine horizontalLine1Clone = HorizontalLine( - y: 12, - color: Colors.red, - dashArray: [0, 1], - strokeWidth: 21, - label: horizontalLineLabel1, -); -final HorizontalLine horizontalLine2 = HorizontalLine( - y: 12, - color: Colors.red, - dashArray: [0, 1, 3], - strokeWidth: 21, - label: horizontalLineLabel1, -); -final HorizontalLine horizontalLine3 = HorizontalLine( - y: 12, - color: Colors.red, - dashArray: [0, 1], - strokeWidth: 22, - label: horizontalLineLabel1, -); -final HorizontalLine horizontalLine4 = HorizontalLine( - y: 12, - color: Colors.red, - dashArray: [1, 0], - strokeWidth: 21, - label: horizontalLineLabel1, -); -final HorizontalLine horizontalLine5 = HorizontalLine( - y: 33, - color: Colors.red, - dashArray: [0, 1], - strokeWidth: 21, - label: horizontalLineLabel1, -); -final HorizontalLine horizontalLine6 = HorizontalLine( - y: 12, - color: Colors.green, - dashArray: [0, 1], - strokeWidth: 21, - label: horizontalLineLabel1, -); -final HorizontalLine horizontalLine7 = HorizontalLine( - y: 12, - color: Colors.red, - dashArray: [0, 1], - strokeWidth: 21, - label: horizontalLineLabel2, -); -final HorizontalLine horizontalLine8 = HorizontalLine( - y: 12, - color: Colors.red, - strokeWidth: 21, - label: horizontalLineLabel1, +final candlestickSpot5 = CandlestickSpot( + x: -50, + open: -40, + high: -130, + low: -30, + close: -50, ); -final HorizontalLine horizontalLine9 = HorizontalLine( - y: 12, - color: Colors.red, - dashArray: [0, 12, 44], - strokeWidth: 21, - label: horizontalLineLabel1, +final candlestickTouchData1 = CandlestickTouchData( + enabled: false, ); +final candlestickTouchedSpot1 = CandlestickTouchedSpot(candlestickSpot1, 0); -final VerticalLine verticalLine1 = VerticalLine( - x: 12, - color: Colors.red, - dashArray: [0, 1], - strokeWidth: 21, - label: verticalLineLabel1, -); -final VerticalLine verticalLine1Clone = VerticalLine( - x: 12, - color: Colors.red, - dashArray: [0, 1], - strokeWidth: 21, - label: verticalLineLabel1, -); -final VerticalLine verticalLine2 = VerticalLine( - x: 12, - color: Colors.green, - dashArray: [0, 1], - strokeWidth: 21, - label: verticalLineLabel1, -); -final VerticalLine verticalLine3 = VerticalLine( - x: 12, - color: Colors.red, - dashArray: [0, 1], - strokeWidth: 22, - label: verticalLineLabel1, -); -final VerticalLine verticalLine4 = VerticalLine( - x: 12, - color: Colors.red, - dashArray: [1, 0], - strokeWidth: 21, - label: verticalLineLabel1, -); -final VerticalLine verticalLine5 = VerticalLine( - x: 33, - color: Colors.red, - dashArray: [0, 1], - strokeWidth: 21, - label: verticalLineLabel1, +final CandlestickTouchTooltipData candlestickTouchTooltipData1 = + CandlestickTouchTooltipData( + tooltipBorderRadius: const BorderRadius.all(Radius.circular(23)), + tooltipPadding: const EdgeInsets.all(11), + getTooltipColor: candlestickChartGetTooltipGreenColor, + maxContentWidth: 33, + fitInsideVertically: true, + fitInsideHorizontally: false, + getTooltipItems: candlestickChartGetTooltipItems, + tooltipBorder: const BorderSide(color: Colors.red), ); -final VerticalLine verticalLine6 = VerticalLine( - x: 12, - color: Colors.green, - dashArray: [0, 1], - strokeWidth: 21, - label: verticalLineLabel1, +final CandlestickTouchTooltipData candlestickTouchTooltipData1Clone = + CandlestickTouchTooltipData( + tooltipBorderRadius: const BorderRadius.all(Radius.circular(23)), + tooltipPadding: const EdgeInsets.all(11), + getTooltipColor: candlestickChartGetTooltipGreenColor, + maxContentWidth: 33, + fitInsideVertically: true, + fitInsideHorizontally: false, + getTooltipItems: candlestickChartGetTooltipItems, + tooltipBorder: const BorderSide(color: Colors.red), ); -final VerticalLine verticalLine7 = VerticalLine( - x: 12, - color: Colors.red, - dashArray: [0, 1], - strokeWidth: 21, - label: verticalLineLabel2, +final CandlestickTouchTooltipData candlestickTouchTooltipData2 = + CandlestickTouchTooltipData( + tooltipBorderRadius: const BorderRadius.all(Radius.circular(23)), + tooltipPadding: const EdgeInsets.all(11), + getTooltipColor: candlestickChartGetTooltipGreenColor, + maxContentWidth: 33, + fitInsideVertically: true, + fitInsideHorizontally: false, + getTooltipItems: candlestickChartGetTooltipItems, + tooltipBorder: const BorderSide(color: Colors.blue), + tooltipHorizontalAlignment: FLHorizontalAlignment.left, ); -final VerticalLine verticalLine8 = VerticalLine( - x: 12, - color: Colors.red, - strokeWidth: 21, - label: verticalLineLabel1, +final CandlestickTouchTooltipData candlestickTouchTooltipData3 = + CandlestickTouchTooltipData( + tooltipBorderRadius: const BorderRadius.all(Radius.circular(23)), + tooltipPadding: const EdgeInsets.all(11), + getTooltipColor: candlestickChartGetTooltipGreenColor, + maxContentWidth: 33, + fitInsideVertically: true, + fitInsideHorizontally: false, + getTooltipItems: candlestickChartGetTooltipItems, + tooltipBorder: const BorderSide(color: Colors.red, width: 2), + tooltipHorizontalAlignment: FLHorizontalAlignment.right, + tooltipHorizontalOffset: 10, ); -final VerticalLine verticalLine9 = VerticalLine( - x: 12, - color: Colors.red, - dashArray: [0, 12, 44], - strokeWidth: 21, - label: verticalLineLabel1, +final DefaultTextStyle defaultTextStyle1 = DefaultTextStyle( + style: const TextStyle(), + child: Container(), ); - final ExtraLinesData extraLinesData1 = ExtraLinesData( horizontalLines: [ horizontalLine1, @@ -1661,7 +1270,6 @@ final ExtraLinesData extraLinesData1Clone = ExtraLinesData( ], extraLinesOnTop: false, ); - final ExtraLinesData extraLinesData2 = ExtraLinesData( horizontalLines: [ horizontalLine3, @@ -1686,6 +1294,7 @@ final ExtraLinesData extraLinesData3 = ExtraLinesData( ], extraLinesOnTop: false, ); + final ExtraLinesData extraLinesData4 = ExtraLinesData( horizontalLines: [ horizontalLine1, @@ -1714,359 +1323,516 @@ final ExtraLinesData extraLinesData6 = ExtraLinesData( verticalLine3, ], ); - -final SizedPicture sizedPicture1 = SizedPicture( - PictureRecorder().endRecording(), - 10, - 30, -); -final SizedPicture sizedPicture1Clone = SizedPicture( - PictureRecorder().endRecording(), - 10, - 30, +final FlGridData flGridData2 = FlGridData( + verticalInterval: 12, + horizontalInterval: 22, + drawVerticalLine: false, + checkToShowVerticalLine: checkToShowLine, + getDrawingHorizontalLine: getDrawingLine, + getDrawingVerticalLine: (value) => flLine1, ); +final FlSpot flSpot1Clone = flSpot1.copyWith(); +final FlSpot flSpot2Clone = flSpot2.copyWith(); -final SizedPicture sizedPicture2 = SizedPicture( - PictureRecorder().endRecording(), - 11, - 30, +final GaugeChartData gaugeChartData1 = GaugeChartData( + startDegreeOffset: 25, + sweepAngle: 65, + defaultRingWidth: 45, + rings: const [gaugeRing1], + touchData: gaugeTouchData1, +); +final GaugeChartData gaugeChartData1Clone = gaugeChartData1.copyWith(); +const GaugeProgressRing gaugeRing1 = GaugeProgressRing( + value: 0.2, + color: Colors.black, + backgroundColor: Colors.amber, + strokeCap: StrokeCap.round, +); +const GaugeProgressRing gaugeRing2 = GaugeProgressRing( + value: 0.8, + color: Colors.red, + width: 20, ); -final SizedPicture sizedPicture3 = SizedPicture( - PictureRecorder().endRecording(), - 10, - 32, +const GaugeZone gaugeZone1 = GaugeZone(from: 0, to: 0.3, color: Colors.red); +const GaugeZone gaugeZone2 = GaugeZone(from: 0.3, to: 0.7, color: Colors.amber); +const GaugeZone gaugeZone3 = GaugeZone(from: 0.7, to: 1, color: Colors.green); +const GaugeZonesRing gaugeZonesRing1 = GaugeZonesRing( + zones: [gaugeZone1, gaugeZone2, gaugeZone3], + zonesSpace: 2, + width: 8, ); -final SizedPicture sizedPicture4 = SizedPicture( - PictureRecorder().endRecording(), - 442, - 30, +const GaugePointer gaugePointer1 = GaugePointer( + value: 0.6, + painter: GaugePointerNeedlePainter(length: 40, width: 6), ); - -final BetweenBarsData betweenBarsData1 = BetweenBarsData( - fromIndex: 1, - toIndex: 2, - gradient: const LinearGradient( - begin: Alignment(1, 3), - end: Alignment(4, 1), - stops: [1, 2, 3], - colors: [Colors.green, Colors.blue, Colors.red], - ), +final GaugeTouchData gaugeTouchData1 = GaugeTouchData( + enabled: true, + touchCallback: (_, __) {}, ); -final BetweenBarsData betweenBarsData1Clone = BetweenBarsData( - fromIndex: 1, - toIndex: 2, - gradient: const LinearGradient( - begin: Alignment(1, 3), - end: Alignment(4, 1), - stops: [1, 2, 3], - colors: [Colors.green, Colors.blue, Colors.red], - ), +final GaugeTouchData gaugeTouchData1Clone = gaugeTouchData1; +final GaugeTouchData gaugeTouchData2 = GaugeTouchData( + enabled: false, + touchCallback: (_, __) {}, + mouseCursorResolver: (_, __) => MouseCursor.defer, +); +const GaugeTouchedRing gaugeTouchedRing1 = GaugeTouchedRing( + touchedRing: gaugeRing1, + touchedRingIndex: 0, + touchAngle: 45, + touchRadius: 100, + touchValue: 0.1, + isOnValue: true, +); +const GaugeTouchedRing gaugeTouchedRing2 = GaugeTouchedRing( + touchedRing: gaugeRing2, + touchedRingIndex: 1, + touchAngle: 90, + touchRadius: 110, + touchValue: 0.5, + isOnValue: true, +); +const GaugeTouchedRing gaugeTouchedRing3 = GaugeTouchedRing( + touchedRing: null, + touchedRingIndex: -1, + touchAngle: 180, + touchRadius: 200, + touchValue: 0.7, + isOnValue: false, +); +const GaugeTouchedRing gaugeTouchedRingClone1 = gaugeTouchedRing1; +final HorizontalLine horizontalLine1 = HorizontalLine( + y: 12, + color: Colors.red, + dashArray: [0, 1], + strokeWidth: 21, + label: horizontalLineLabel1, ); -final BetweenBarsData betweenBarsData2 = BetweenBarsData( - fromIndex: 2, - toIndex: 2, - gradient: const LinearGradient( - begin: Alignment(1, 3), - end: Alignment(4, 1), - stops: [1, 2, 3], - colors: [Colors.green, Colors.blue, Colors.red], - ), +final HorizontalLine horizontalLine1Clone = HorizontalLine( + y: 12, + color: Colors.red, + dashArray: [0, 1], + strokeWidth: 21, + label: horizontalLineLabel1, ); -final BetweenBarsData betweenBarsData3 = BetweenBarsData( - fromIndex: 1, - toIndex: 1, - gradient: const LinearGradient( - begin: Alignment(1, 4), - end: Alignment(4, 1), - stops: [1, 2, 3], - colors: [Colors.green, Colors.blue, Colors.red], - ), +final HorizontalLine horizontalLine2 = HorizontalLine( + y: 12, + color: Colors.red, + dashArray: [0, 1, 3], + strokeWidth: 21, + label: horizontalLineLabel1, ); -final BetweenBarsData betweenBarsData4 = BetweenBarsData( - fromIndex: 1, - toIndex: 2, - gradient: const LinearGradient( - begin: Alignment(1, 3), - end: Alignment(5, 1), - stops: [1, 2, 3], - colors: [Colors.green, Colors.blue, Colors.red], - ), +final HorizontalLine horizontalLine3 = HorizontalLine( + y: 12, + color: Colors.red, + dashArray: [0, 1], + strokeWidth: 22, + label: horizontalLineLabel1, ); -final BetweenBarsData betweenBarsData5 = BetweenBarsData( - fromIndex: 1, - toIndex: 2, - gradient: const LinearGradient( - begin: Alignment(1, 3), - end: Alignment(4, 1), - colors: [Colors.green, Colors.blue, Colors.red], - ), +final HorizontalLine horizontalLine4 = HorizontalLine( + y: 12, + color: Colors.red, + dashArray: [1, 0], + strokeWidth: 21, + label: horizontalLineLabel1, ); -final BetweenBarsData betweenBarsData6 = BetweenBarsData( - fromIndex: 1, - toIndex: 2, - gradient: const LinearGradient( - begin: Alignment(1, 3), - end: Alignment(4, 1), - stops: [1, 2, 3], - colors: [Colors.green, Colors.blue], - ), +final HorizontalLine horizontalLine5 = HorizontalLine( + y: 33, + color: Colors.red, + dashArray: [0, 1], + strokeWidth: 21, + label: horizontalLineLabel1, ); -final BetweenBarsData betweenBarsData7 = BetweenBarsData( - fromIndex: 1, - toIndex: 2, - gradient: const LinearGradient( - begin: Alignment(1, 22), - end: Alignment(4, 1), - stops: [1, 2, 3], - colors: [Colors.green, Colors.blue], - ), +final HorizontalLine horizontalLine6 = HorizontalLine( + y: 12, + color: Colors.green, + dashArray: [0, 1], + strokeWidth: 21, + label: horizontalLineLabel1, ); -final BetweenBarsData betweenBarsData8 = BetweenBarsData( - fromIndex: 1, - toIndex: 2, - gradient: const LinearGradient( - begin: Alignment(1, 3), - end: Alignment(4, 1), - stops: [1, 2, 3], - colors: [], - ), +final HorizontalLine horizontalLine7 = HorizontalLine( + y: 12, + color: Colors.red, + dashArray: [0, 1], + strokeWidth: 21, + label: horizontalLineLabel2, ); - -final ShowingTooltipIndicators showingTooltipIndicator1 = - ShowingTooltipIndicators( - [lineBarSpot1, lineBarSpot2], +final HorizontalLine horizontalLine8 = HorizontalLine( + y: 12, + color: Colors.red, + strokeWidth: 21, + label: horizontalLineLabel1, ); -final ShowingTooltipIndicators showingTooltipIndicator1Clone = - ShowingTooltipIndicators( - [lineBarSpot1, lineBarSpot2], +final HorizontalLine horizontalLine9 = HorizontalLine( + y: 12, + color: Colors.red, + dashArray: [0, 12, 44], + strokeWidth: 21, + label: horizontalLineLabel1, ); -const ShowingTooltipIndicators showingTooltipIndicator2 = - ShowingTooltipIndicators( - [], +final HorizontalLineLabel horizontalLineLabel1 = HorizontalLineLabel( + show: true, + style: const TextStyle(color: Colors.green), + labelResolver: horizontalLabelResolver, + alignment: Alignment.topCenter, + padding: const EdgeInsets.all(12), + direction: LabelDirection.vertical, ); -final ShowingTooltipIndicators showingTooltipIndicator3 = - ShowingTooltipIndicators( - [lineBarSpot2], + +final HorizontalLineLabel horizontalLineLabel1Clone = HorizontalLineLabel( + show: true, + style: const TextStyle(color: Colors.green), + labelResolver: horizontalLabelResolver, + alignment: Alignment.topCenter, + padding: const EdgeInsets.all(12), + direction: LabelDirection.vertical, ); -final ShowingTooltipIndicators showingTooltipIndicator4 = - ShowingTooltipIndicators( - [lineBarSpot2, lineBarSpot1], +final HorizontalLineLabel horizontalLineLabel2 = HorizontalLineLabel( + style: const TextStyle(color: Colors.green), + labelResolver: horizontalLabelResolver, + alignment: Alignment.topCenter, + padding: const EdgeInsets.all(12), ); -final ShowingTooltipIndicators showingTooltipIndicator5 = - ShowingTooltipIndicators( - [lineBarSpot1, lineBarSpot2, lineBarSpot2], + +final HorizontalLineLabel horizontalLineLabel3 = HorizontalLineLabel( + show: true, + labelResolver: horizontalLabelResolver, + alignment: Alignment.topCenter, + padding: const EdgeInsets.all(12), ); -final LineChartData lineChartData1 = LineChartData( - borderData: borderData1, - lineTouchData: lineTouchData1, - showingTooltipIndicators: [ - showingTooltipIndicator1, - showingTooltipIndicator2, - ], - backgroundColor: Colors.red, - maxY: 23, - rangeAnnotations: rangeAnnotations1, - gridData: flGridData1, - titlesData: MockData.flTitlesData1, - lineBarsData: [lineChartBarData1, lineChartBarData2, lineChartBarData3], - betweenBarsData: [betweenBarsData1, betweenBarsData2, betweenBarsData3], - extraLinesData: extraLinesData1, - maxX: 23, - minX: 11, - minY: 43, +final HorizontalLineLabel horizontalLineLabel4 = HorizontalLineLabel( + show: true, + style: const TextStyle(color: Colors.green), + alignment: Alignment.topCenter, + padding: const EdgeInsets.all(12), ); -final LineChartData lineChartData1Clone = LineChartData( - borderData: borderData1Clone, - lineTouchData: lineTouchData1Clone, - showingTooltipIndicators: [ - showingTooltipIndicator1Clone, - showingTooltipIndicator2, - ], - backgroundColor: Colors.red, - maxY: 23, - rangeAnnotations: rangeAnnotations1, - gridData: flGridData1Clone, - titlesData: MockData.flTitlesData1Clone, - lineBarsData: [lineChartBarData1Clone, lineChartBarData2, lineChartBarData3], - betweenBarsData: [betweenBarsData1Clone, betweenBarsData2, betweenBarsData3], - extraLinesData: extraLinesData1Clone, - maxX: 23, - minX: 11, - minY: 43, + +final HorizontalLineLabel horizontalLineLabel5 = HorizontalLineLabel( + show: true, + style: const TextStyle(color: Colors.green), + labelResolver: horizontalLabelResolver, + alignment: Alignment.bottomRight, + padding: const EdgeInsets.all(12), ); -final LineChartData lineChartData2 = LineChartData( - lineTouchData: lineTouchData1, - showingTooltipIndicators: [ - showingTooltipIndicator1, - showingTooltipIndicator2, - ], - backgroundColor: Colors.red, - maxY: 23, - rangeAnnotations: rangeAnnotations1, - gridData: flGridData1, - titlesData: MockData.flTitlesData1, - lineBarsData: [lineChartBarData1, lineChartBarData2, lineChartBarData3], - betweenBarsData: [betweenBarsData1, betweenBarsData2, betweenBarsData3], - extraLinesData: extraLinesData1, - maxX: 23, - minX: 11, - minY: 43, + +final HorizontalLineLabel horizontalLineLabel6 = HorizontalLineLabel( + show: true, + style: const TextStyle(color: Colors.green), + labelResolver: horizontalLabelResolver, + alignment: Alignment.topCenter, + padding: const EdgeInsets.all(44), ); -final LineChartData lineChartData3 = LineChartData( - borderData: borderData1, - lineTouchData: lineTouchData2, - showingTooltipIndicators: [ - showingTooltipIndicator1, - showingTooltipIndicator2, - ], - backgroundColor: Colors.red, - maxY: 23, - rangeAnnotations: rangeAnnotations1, - gridData: flGridData1, - titlesData: MockData.flTitlesData1, - lineBarsData: [lineChartBarData1, lineChartBarData2, lineChartBarData3], - betweenBarsData: [betweenBarsData1, betweenBarsData2, betweenBarsData3], - extraLinesData: extraLinesData1, - maxX: 23, - minX: 11, - minY: 43, + +final HorizontalLineLabel horizontalLineLabel7 = HorizontalLineLabel( + style: const TextStyle(color: Colors.green), + labelResolver: horizontalLabelResolver, + alignment: Alignment.topCenter, + padding: const EdgeInsets.all(12), + direction: LabelDirection.vertical, ); -final LineChartData lineChartData4 = LineChartData( - borderData: borderData1, - lineTouchData: lineTouchData1, - showingTooltipIndicators: [], - backgroundColor: Colors.red, - maxY: 23, - rangeAnnotations: rangeAnnotations1, - gridData: flGridData1, - titlesData: MockData.flTitlesData1, - lineBarsData: [lineChartBarData1, lineChartBarData2, lineChartBarData3], - betweenBarsData: [betweenBarsData1, betweenBarsData2, betweenBarsData3], - extraLinesData: extraLinesData1, - maxX: 23, - minX: 11, - minY: 43, + +final HorizontalRangeAnnotation horizontalRangeAnnotation1 = + HorizontalRangeAnnotation(color: Colors.green, y2: 12, y1: 12.1); +final HorizontalRangeAnnotation horizontalRangeAnnotation1Clone = + HorizontalRangeAnnotation(color: Colors.green, y2: 12, y1: 12.1); +final TouchLineBarSpot lineBarSpot1 = TouchLineBarSpot( + lineChartBarData1, + 0, + flSpot1, + 0, ); -final LineChartData lineChartData5 = LineChartData( - borderData: borderData1, - lineTouchData: lineTouchData1, - showingTooltipIndicators: [ - showingTooltipIndicator2, - showingTooltipIndicator1, - ], - backgroundColor: Colors.red, - maxY: 23, - rangeAnnotations: rangeAnnotations1, - gridData: flGridData1, - titlesData: MockData.flTitlesData1, - lineBarsData: [lineChartBarData1, lineChartBarData2, lineChartBarData3], - betweenBarsData: [betweenBarsData1, betweenBarsData2, betweenBarsData3], - extraLinesData: extraLinesData1, - maxX: 23, - minX: 11, - minY: 43, +final TouchLineBarSpot lineBarSpot1Clone = TouchLineBarSpot( + lineChartBarData1Clone, + 0, + flSpot1Clone, + 0, ); -final LineChartData lineChartData6 = LineChartData( - borderData: borderData1, - lineTouchData: lineTouchData1, - backgroundColor: Colors.red, - maxY: 23, - rangeAnnotations: rangeAnnotations1, - gridData: flGridData1, - titlesData: MockData.flTitlesData1, - lineBarsData: [lineChartBarData1, lineChartBarData2, lineChartBarData3], - betweenBarsData: [betweenBarsData1, betweenBarsData2, betweenBarsData3], - extraLinesData: extraLinesData1, - maxX: 23, - minX: 11, - minY: 43, +final TouchLineBarSpot lineBarSpot2 = + TouchLineBarSpot(lineChartBarData1, 2, flSpot1, 2); +final TouchLineBarSpot lineBarSpot3 = TouchLineBarSpot( + lineChartBarData1, + 100, + flSpot1, + 2, ); -final LineChartData lineChartData7 = LineChartData( - borderData: borderData1, - lineTouchData: lineTouchData1, - showingTooltipIndicators: [ - showingTooltipIndicator1, - showingTooltipIndicator2, + +final LineChartBarData lineChartBarData1 = LineChartBarData( + dashArray: [0, 1], + gradient: const LinearGradient( + colors: [Colors.red, Colors.green], + stops: [0, 1], + begin: Alignment.center, + end: Alignment.bottomRight, + ), + spots: [ + flSpot1, + flSpot2, ], - backgroundColor: Colors.red, - maxY: 23, - rangeAnnotations: rangeAnnotations1, - gridData: flGridData1, - titlesData: MockData.flTitlesData2, - lineBarsData: [lineChartBarData1, lineChartBarData2, lineChartBarData3], - betweenBarsData: [betweenBarsData1, betweenBarsData2, betweenBarsData3], - extraLinesData: extraLinesData1, - maxX: 23, - minX: 11, - minY: 43, + shadow: shadow1, + aboveBarData: barAreaData1, + belowBarData: barAreaData2, + barWidth: 12, + curveSmoothness: 12, + dotData: flDotData1, + isStrokeCapRound: true, + preventCurveOvershootingThreshold: 1.2, + showingIndicators: [0, 1], + errorIndicatorData: const FlErrorIndicatorData( + show: false, + ), ); -final LineChartData lineChartData8 = LineChartData( - borderData: borderData1, - lineTouchData: lineTouchData1, - showingTooltipIndicators: [ - showingTooltipIndicator1, - showingTooltipIndicator2, + +final LineChartBarData lineChartBarData1Clone = LineChartBarData( + dashArray: [0, 1], + gradient: const LinearGradient( + colors: [Colors.red, Colors.green], + stops: [0, 1], + begin: Alignment.center, + end: Alignment.bottomRight, + ), + spots: [ + flSpot1Clone, + flSpot2, ], - clipData: const FlClipData.all(), - backgroundColor: Colors.red, - maxY: 23, - rangeAnnotations: rangeAnnotations1, - gridData: flGridData1, - titlesData: MockData.flTitlesData1, - lineBarsData: [lineChartBarData1, lineChartBarData2, lineChartBarData3], - betweenBarsData: [betweenBarsData1, betweenBarsData2, betweenBarsData3], - extraLinesData: extraLinesData1, - maxX: 23, - minX: 11, - minY: 43, + shadow: shadow1Clone, + aboveBarData: barAreaData1Clone, + belowBarData: barAreaData2, + barWidth: 12, + curveSmoothness: 12, + dotData: flDotData1Clone, + isStrokeCapRound: true, + preventCurveOvershootingThreshold: 1.2, + showingIndicators: [0, 1], + errorIndicatorData: const FlErrorIndicatorData( + show: false, + ), ); -final LineChartData lineChartData9 = LineChartData( - borderData: borderData1, - lineTouchData: lineTouchData1, - showingTooltipIndicators: [ - showingTooltipIndicator1, - showingTooltipIndicator2, + +final LineChartBarData lineChartBarData2 = LineChartBarData( + dashArray: [0, 1], + gradient: const LinearGradient( + colors: [Colors.red, Colors.green], + stops: [0, 1], + begin: Alignment.center, + end: Alignment.bottomRight, + ), + spots: [ + flSpot1, + flSpot2, ], - backgroundColor: Colors.red.withValues(alpha: 0.2), - maxY: 23, - rangeAnnotations: rangeAnnotations1, - gridData: flGridData1, - titlesData: MockData.flTitlesData1, - lineBarsData: [lineChartBarData1, lineChartBarData2, lineChartBarData3], - betweenBarsData: [betweenBarsData1, betweenBarsData2, betweenBarsData3], - extraLinesData: extraLinesData1, - maxX: 23, - minX: 11, - minY: 43, + shadow: shadow2, + isStepLineChart: true, + aboveBarData: barAreaData1, + belowBarData: barAreaData2, + barWidth: 12, + curveSmoothness: 12, + dotData: flDotData1, + isStrokeCapRound: true, + preventCurveOvershootingThreshold: 1.2, + showingIndicators: [0, 4], ); -final LineChartData lineChartData10 = LineChartData( - borderData: borderData1, - lineTouchData: lineTouchData1, - showingTooltipIndicators: [ - showingTooltipIndicator1, - showingTooltipIndicator2, +final LineChartBarData lineChartBarData3 = LineChartBarData( + gradient: const LinearGradient( + colors: [Colors.red, Colors.green], + stops: [0, 1], + begin: Alignment.center, + end: Alignment.bottomRight, + ), + spots: [ + flSpot1, + flSpot2, ], - backgroundColor: Colors.red, - maxY: 24, - rangeAnnotations: rangeAnnotations1, - gridData: flGridData1, - titlesData: MockData.flTitlesData1, - lineBarsData: [lineChartBarData1, lineChartBarData2, lineChartBarData3], - betweenBarsData: [betweenBarsData1, betweenBarsData2, betweenBarsData3], - extraLinesData: extraLinesData1, - maxX: 23, - minX: 11, - minY: 43, + shadow: shadow3, + isStepLineChart: true, + lineChartStepData: lineChartStepData2, + aboveBarData: barAreaData1, + belowBarData: barAreaData2, + barWidth: 12, + curveSmoothness: 12, + dotData: flDotData1, + isStrokeCapRound: true, + preventCurveOvershootingThreshold: 1.2, + showingIndicators: [0, 1], ); -final LineChartData lineChartData11 = LineChartData( - borderData: borderData1, - lineTouchData: lineTouchData1, - showingTooltipIndicators: [ - showingTooltipIndicator1, - showingTooltipIndicator2, +final LineChartBarData lineChartBarData4 = LineChartBarData( + dashArray: [0, 1], + gradient: const LinearGradient( + colors: [Colors.red, Colors.green], + stops: [0, 1], + begin: Alignment.center, + end: Alignment.bottomRight, + ), + spots: [ + flSpot2, + flSpot1, ], - backgroundColor: Colors.red, + shadow: shadow4, + lineChartStepData: lineChartStepData2, + aboveBarData: barAreaData1, + belowBarData: barAreaData2, + barWidth: 12, + curveSmoothness: 12, + dotData: flDotData1, + isStrokeCapRound: true, + preventCurveOvershootingThreshold: 1.2, + showingIndicators: [0, 1], +); +final LineChartBarData lineChartBarData5 = LineChartBarData( + dashArray: [0, 1], + gradient: const LinearGradient( + colors: [Colors.red, Colors.green], + stops: [0, 1], + begin: Alignment.center, + end: Alignment.bottomRight, + ), + spots: [ + flSpot1, + flSpot2, + ], + aboveBarData: barAreaData2, + belowBarData: barAreaData1, + barWidth: 12, + curveSmoothness: 12, + dotData: flDotData1, + isStrokeCapRound: true, + preventCurveOvershootingThreshold: 1.2, + showingIndicators: [0, 1], +); +final LineChartBarData lineChartBarData6 = LineChartBarData( + dashArray: [0, 1], + gradient: const LinearGradient( + colors: [Colors.red, Colors.green], + stops: [0, 1], + begin: Alignment.center, + end: Alignment.bottomRight, + ), + spots: [ + flSpot1, + flSpot2, + ], + aboveBarData: barAreaData1, + belowBarData: barAreaData2, + barWidth: 12, + curveSmoothness: 12, + dotData: flDotData1, + isStrokeCapRound: true, + preventCurveOvershootingThreshold: 1.2, + showingIndicators: [0, 1], +); +final LineChartBarData lineChartBarData7 = LineChartBarData( + dashArray: [0, 1], + gradient: LinearGradient( + colors: [Colors.red, Colors.green.withValues(alpha: 0.4)], + stops: const [0, 1], + begin: Alignment.center, + end: Alignment.bottomRight, + ), + spots: [ + flSpot1, + flSpot2, + ], + aboveBarData: barAreaData1, + belowBarData: barAreaData2, + barWidth: 12, + curveSmoothness: 12, + dotData: flDotData1, + isStrokeCapRound: true, + preventCurveOvershootingThreshold: 1.2, + showingIndicators: [0, 1], +); + +final LineChartBarData lineChartBarData8 = LineChartBarData( + dashArray: [0, 1], + gradient: const LinearGradient( + colors: [Colors.red, Colors.green], + stops: [0, 1], + begin: Alignment.center, + end: Alignment.bottomRight, + ), + spots: [ + flSpot1, + flSpot2, + ], + aboveBarData: barAreaData1, + belowBarData: barAreaData2, + barWidth: 12, + curveSmoothness: 12.01, + dotData: flDotData1, + isStrokeCapRound: true, + preventCurveOvershootingThreshold: 1.2, + showingIndicators: [0, 1], +); +final LineChartBarData lineChartBarData9 = LineChartBarData( + dashArray: [0, 1], + gradient: const LinearGradient( + colors: [Colors.red, Colors.green], + stops: [0, 1], + begin: Alignment.center, + end: Alignment.bottomRight, + ), + spots: [ + flSpot1, + flSpot2, + ], + aboveBarData: barAreaData1, + belowBarData: barAreaData2, + barWidth: 12, + curveSmoothness: 12, + dotData: flDotData1, + isStrokeCapRound: true, + preventCurveOverShooting: true, + preventCurveOvershootingThreshold: 1.2, + showingIndicators: [0, 1], +); + +final LineChartData lineChartData1 = LineChartData( + borderData: borderData1, + lineTouchData: lineTouchData1, + showingTooltipIndicators: [ + showingTooltipIndicator1, + showingTooltipIndicator2, + ], + backgroundColor: Colors.red, + maxY: 23, + rangeAnnotations: rangeAnnotations1, + gridData: flGridData1, + titlesData: MockData.flTitlesData1, + lineBarsData: [lineChartBarData1, lineChartBarData2, lineChartBarData3], + betweenBarsData: [betweenBarsData1, betweenBarsData2, betweenBarsData3], + extraLinesData: extraLinesData1, + maxX: 23, + minX: 11, + minY: 43, +); + +final LineChartData lineChartData10 = LineChartData( + borderData: borderData1, + lineTouchData: lineTouchData1, + showingTooltipIndicators: [ + showingTooltipIndicator1, + showingTooltipIndicator2, + ], + backgroundColor: Colors.red, + maxY: 24, + rangeAnnotations: rangeAnnotations1, + gridData: flGridData1, + titlesData: MockData.flTitlesData1, + lineBarsData: [lineChartBarData1, lineChartBarData2, lineChartBarData3], + betweenBarsData: [betweenBarsData1, betweenBarsData2, betweenBarsData3], + extraLinesData: extraLinesData1, + maxX: 23, + minX: 11, + minY: 43, +); + +final LineChartData lineChartData11 = LineChartData( + borderData: borderData1, + lineTouchData: lineTouchData1, + showingTooltipIndicators: [ + showingTooltipIndicator1, + showingTooltipIndicator2, + ], + backgroundColor: Colors.red, maxY: 23, gridData: flGridData1, titlesData: MockData.flTitlesData1, @@ -2077,6 +1843,7 @@ final LineChartData lineChartData11 = LineChartData( minX: 11, minY: 43, ); + final LineChartData lineChartData12 = LineChartData( borderData: borderData1, lineTouchData: lineTouchData1, @@ -2152,6 +1919,7 @@ final LineChartData lineChartData15 = LineChartData( minX: 11, minY: 43, ); + final LineChartData lineChartData16 = LineChartData( borderData: borderData1, lineTouchData: lineTouchData1, @@ -2171,6 +1939,7 @@ final LineChartData lineChartData16 = LineChartData( minX: 11, minY: 43, ); + final LineChartData lineChartData17 = LineChartData( borderData: borderData1, lineTouchData: lineTouchData1, @@ -2190,6 +1959,7 @@ final LineChartData lineChartData17 = LineChartData( minX: 11, minY: 43, ); + final LineChartData lineChartData18 = LineChartData( borderData: borderData1, lineTouchData: lineTouchData1, @@ -2228,6 +1998,43 @@ final LineChartData lineChartData19 = LineChartData( minX: 44, minY: 43, ); +final LineChartData lineChartData1Clone = LineChartData( + borderData: borderData1Clone, + lineTouchData: lineTouchData1Clone, + showingTooltipIndicators: [ + showingTooltipIndicator1Clone, + showingTooltipIndicator2, + ], + backgroundColor: Colors.red, + maxY: 23, + rangeAnnotations: rangeAnnotations1, + gridData: flGridData1Clone, + titlesData: MockData.flTitlesData1Clone, + lineBarsData: [lineChartBarData1Clone, lineChartBarData2, lineChartBarData3], + betweenBarsData: [betweenBarsData1Clone, betweenBarsData2, betweenBarsData3], + extraLinesData: extraLinesData1Clone, + maxX: 23, + minX: 11, + minY: 43, +); +final LineChartData lineChartData2 = LineChartData( + lineTouchData: lineTouchData1, + showingTooltipIndicators: [ + showingTooltipIndicator1, + showingTooltipIndicator2, + ], + backgroundColor: Colors.red, + maxY: 23, + rangeAnnotations: rangeAnnotations1, + gridData: flGridData1, + titlesData: MockData.flTitlesData1, + lineBarsData: [lineChartBarData1, lineChartBarData2, lineChartBarData3], + betweenBarsData: [betweenBarsData1, betweenBarsData2, betweenBarsData3], + extraLinesData: extraLinesData1, + maxX: 23, + minX: 11, + minY: 43, +); final LineChartData lineChartData20 = LineChartData( borderData: borderData1, lineTouchData: lineTouchData1, @@ -2267,1234 +2074,1509 @@ final LineChartData lineChartData21 = LineChartData( minX: 11, minY: 302, ); - -final PieChartData pieChartData1 = PieChartData( - borderData: FlBorderData(show: false, border: Border.all()), - startDegreeOffset: 0, - sections: [ - PieChartSectionData(value: 12, color: Colors.red), - PieChartSectionData(value: 22, color: Colors.green), +final LineChartData lineChartData3 = LineChartData( + borderData: borderData1, + lineTouchData: lineTouchData2, + showingTooltipIndicators: [ + showingTooltipIndicator1, + showingTooltipIndicator2, ], - centerSpaceColor: Colors.white, - centerSpaceRadius: 12, - pieTouchData: PieTouchData( - enabled: false, - ), - sectionsSpace: 44, - titleSunbeamLayout: false, + backgroundColor: Colors.red, + maxY: 23, + rangeAnnotations: rangeAnnotations1, + gridData: flGridData1, + titlesData: MockData.flTitlesData1, + lineBarsData: [lineChartBarData1, lineChartBarData2, lineChartBarData3], + betweenBarsData: [betweenBarsData1, betweenBarsData2, betweenBarsData3], + extraLinesData: extraLinesData1, + maxX: 23, + minX: 11, + minY: 43, ); -final PieChartData pieChartData1Clone = pieChartData1.copyWith(); - -bool gridCheckToShowLine(double value) => true; - -FlLine gridGetDrawingLine(double value) => const FlLine(); - -ScatterTooltipItem? scatterChartGetTooltipItems(ScatterSpot spots) { - return ScatterTooltipItem( - 'check', - textStyle: const TextStyle(color: Colors.blue), - bottomMargin: 23, - ); -} - -Color scatterChartGetTooltipGreenColor(ScatterSpot spots) { - return Colors.green; //Color -} -Color scatterChartGetTooltipRedColor(ScatterSpot spots) { - return Colors.red; //Color -} - -final ScatterSpot scatterSpot1 = ScatterSpot(1, 40); -final ScatterSpot scatterSpot1Clone = ScatterSpot(1, 40); -final ScatterSpot scatterSpot2 = ScatterSpot(-4, -8); -final ScatterSpot scatterSpot2Clone = scatterSpot2.copyWith(); -final ScatterSpot scatterSpot3 = ScatterSpot(-14, 5); -final ScatterSpot scatterSpot4 = ScatterSpot(-0, 0); - -String getLabel(int spotIndex, ScatterSpot spot) => 'label'; - -TextStyle getLabelTextStyle(int spotIndex, ScatterSpot spot) => - const TextStyle(color: Colors.green); - -final ScatterChartData scatterChartData1 = ScatterChartData( - minY: 0, - maxY: 12, - maxX: 22, +final LineChartData lineChartData4 = LineChartData( + borderData: borderData1, + lineTouchData: lineTouchData1, + showingTooltipIndicators: [], + backgroundColor: Colors.red, + maxY: 23, + rangeAnnotations: rangeAnnotations1, + gridData: flGridData1, + titlesData: MockData.flTitlesData1, + lineBarsData: [lineChartBarData1, lineChartBarData2, lineChartBarData3], + betweenBarsData: [betweenBarsData1, betweenBarsData2, betweenBarsData3], + extraLinesData: extraLinesData1, + maxX: 23, minX: 11, - gridData: const FlGridData( - show: false, - getDrawingHorizontalLine: gridGetDrawingLine, - getDrawingVerticalLine: gridGetDrawingLine, - checkToShowHorizontalLine: gridCheckToShowLine, - checkToShowVerticalLine: gridCheckToShowLine, - drawVerticalLine: false, - horizontalInterval: 33, - verticalInterval: 1, - ), - backgroundColor: Colors.black, - clipData: const FlClipData.none(), - borderData: FlBorderData( - show: true, - border: Border.all( - color: Colors.white, - ), - ), - scatterSpots: [ - ScatterSpot( - 0, - 0, - show: false, - dotPainter: FlDotCirclePainter(radius: 33, color: Colors.yellow), - ), - ScatterSpot( - 2, - 2, - show: false, - renderPriority: 10, - dotPainter: FlDotCirclePainter(radius: 11, color: Colors.purple), - ), - ScatterSpot( - 1, - 2, - show: false, - renderPriority: -1, - dotPainter: FlDotCirclePainter(radius: 11, color: Colors.white), - ), - ], - scatterTouchData: ScatterTouchData( - enabled: true, - touchTooltipData: ScatterTouchTooltipData( - getTooltipItems: scatterChartGetTooltipItems, - fitInsideHorizontally: true, - fitInsideVertically: false, - maxContentWidth: 33, - getTooltipColor: (touchedSpot) => Colors.white, - tooltipPadding: const EdgeInsets.all(23), - tooltipBorderRadius: BorderRadius.circular(534), - ), - handleBuiltInTouches: false, - touchCallback: scatterTouchCallback, - touchSpotThreshold: 12, - ), - showingTooltipIndicators: [0, 1, 2], - titlesData: const FlTitlesData( - leftTitles: AxisTitles( - axisNameSize: 33, - axisNameWidget: MockData.widget1, - ), - rightTitles: AxisTitles( - axisNameSize: 1326, - axisNameWidget: MockData.widget3, - sideTitles: SideTitles(reservedSize: 500, showTitles: true), - ), - topTitles: AxisTitles( - axisNameSize: 34, - axisNameWidget: MockData.widget4, - ), - bottomTitles: AxisTitles( - axisNameSize: 22, - axisNameWidget: MockData.widget2, - ), - ), - scatterLabelSettings: ScatterLabelSettings( - showLabel: true, - getLabelTextStyleFunction: getLabelTextStyle, - getLabelFunction: getLabel, - ), + minY: 43, ); -final ScatterChartData scatterChartData1Clone = scatterChartData1.copyWith(); -final scatterTouchTooltipData1 = ScatterTouchTooltipData( - tooltipBorderRadius: BorderRadius.circular(23), - tooltipPadding: const EdgeInsets.all(11), - getTooltipColor: scatterChartGetTooltipGreenColor, - maxContentWidth: 33, - fitInsideVertically: true, - fitInsideHorizontally: false, - getTooltipItems: scatterChartGetTooltipItems, - tooltipBorder: const BorderSide(color: Colors.red), +final LineChartData lineChartData5 = LineChartData( + borderData: borderData1, + lineTouchData: lineTouchData1, + showingTooltipIndicators: [ + showingTooltipIndicator2, + showingTooltipIndicator1, + ], + backgroundColor: Colors.red, + maxY: 23, + rangeAnnotations: rangeAnnotations1, + gridData: flGridData1, + titlesData: MockData.flTitlesData1, + lineBarsData: [lineChartBarData1, lineChartBarData2, lineChartBarData3], + betweenBarsData: [betweenBarsData1, betweenBarsData2, betweenBarsData3], + extraLinesData: extraLinesData1, + maxX: 23, + minX: 11, + minY: 43, ); -final scatterTouchTooltipData1Clone = ScatterTouchTooltipData( - tooltipBorderRadius: BorderRadius.circular(23), - tooltipPadding: const EdgeInsets.all(11), - getTooltipColor: scatterChartGetTooltipGreenColor, - maxContentWidth: 33, - fitInsideVertically: true, - fitInsideHorizontally: false, - getTooltipItems: scatterChartGetTooltipItems, - tooltipBorder: const BorderSide(color: Colors.red), +final LineChartData lineChartData6 = LineChartData( + borderData: borderData1, + lineTouchData: lineTouchData1, + backgroundColor: Colors.red, + maxY: 23, + rangeAnnotations: rangeAnnotations1, + gridData: flGridData1, + titlesData: MockData.flTitlesData1, + lineBarsData: [lineChartBarData1, lineChartBarData2, lineChartBarData3], + betweenBarsData: [betweenBarsData1, betweenBarsData2, betweenBarsData3], + extraLinesData: extraLinesData1, + maxX: 23, + minX: 11, + minY: 43, ); -final scatterTouchTooltipData2 = ScatterTouchTooltipData( - tooltipBorderRadius: BorderRadius.circular(23), - tooltipPadding: const EdgeInsets.all(11), - getTooltipColor: scatterChartGetTooltipGreenColor, - maxContentWidth: 33, - fitInsideVertically: true, - fitInsideHorizontally: false, - getTooltipItems: scatterChartGetTooltipItems, - tooltipBorder: const BorderSide(color: Colors.blue), - tooltipHorizontalAlignment: FLHorizontalAlignment.left, +final LineChartData lineChartData7 = LineChartData( + borderData: borderData1, + lineTouchData: lineTouchData1, + showingTooltipIndicators: [ + showingTooltipIndicator1, + showingTooltipIndicator2, + ], + backgroundColor: Colors.red, + maxY: 23, + rangeAnnotations: rangeAnnotations1, + gridData: flGridData1, + titlesData: MockData.flTitlesData2, + lineBarsData: [lineChartBarData1, lineChartBarData2, lineChartBarData3], + betweenBarsData: [betweenBarsData1, betweenBarsData2, betweenBarsData3], + extraLinesData: extraLinesData1, + maxX: 23, + minX: 11, + minY: 43, ); -final scatterTouchTooltipData3 = ScatterTouchTooltipData( - tooltipBorderRadius: BorderRadius.circular(23), - tooltipPadding: const EdgeInsets.all(11), - getTooltipColor: scatterChartGetTooltipGreenColor, - maxContentWidth: 33, - fitInsideVertically: true, - fitInsideHorizontally: false, - getTooltipItems: scatterChartGetTooltipItems, - tooltipBorder: const BorderSide(color: Colors.red, width: 2), - tooltipHorizontalAlignment: FLHorizontalAlignment.right, - tooltipHorizontalOffset: 10, +final LineChartData lineChartData8 = LineChartData( + borderData: borderData1, + lineTouchData: lineTouchData1, + showingTooltipIndicators: [ + showingTooltipIndicator1, + showingTooltipIndicator2, + ], + clipData: const FlClipData.all(), + backgroundColor: Colors.red, + maxY: 23, + rangeAnnotations: rangeAnnotations1, + gridData: flGridData1, + titlesData: MockData.flTitlesData1, + lineBarsData: [lineChartBarData1, lineChartBarData2, lineChartBarData3], + betweenBarsData: [betweenBarsData1, betweenBarsData2, betweenBarsData3], + extraLinesData: extraLinesData1, + maxX: 23, + minX: 11, + minY: 43, ); - -final BarChartRodStackItem barChartRodStackItem1 = BarChartRodStackItem( - 1, - 2, - Colors.green, - label: 'Test Label', - labelStyle: const TextStyle( - color: Colors.white, - fontSize: 14, - fontWeight: FontWeight.bold, - ), +final LineChartData lineChartData9 = LineChartData( + borderData: borderData1, + lineTouchData: lineTouchData1, + showingTooltipIndicators: [ + showingTooltipIndicator1, + showingTooltipIndicator2, + ], + backgroundColor: Colors.red.withValues(alpha: 0.2), + maxY: 23, + rangeAnnotations: rangeAnnotations1, + gridData: flGridData1, + titlesData: MockData.flTitlesData1, + lineBarsData: [lineChartBarData1, lineChartBarData2, lineChartBarData3], + betweenBarsData: [betweenBarsData1, betweenBarsData2, betweenBarsData3], + extraLinesData: extraLinesData1, + maxX: 23, + minX: 11, + minY: 43, ); -final BarChartRodStackItem barChartRodStackItem1Clone = - barChartRodStackItem1.copyWith(); - -final BarChartRodStackItem barChartRodStackItem2 = BarChartRodStackItem( - 2, - 3, - Colors.green, -); - -final BarChartRodStackItem barChartRodStackItem3 = BarChartRodStackItem( - 3, - 4, - Colors.green, - label: 'This is a very long label that might not fit', - labelStyle: const TextStyle(fontSize: 12), -); - -final BarChartRodStackItem barChartRodStackItem4 = BarChartRodStackItem( - 8, - 10, - Colors.purple, - label: 'Label with emojis 🎯 & symbols!', - labelStyle: const TextStyle(fontWeight: FontWeight.bold), -); - -final BackgroundBarChartRodData backgroundBarChartRodData1 = - BackgroundBarChartRodData( - toY: 21, - color: Colors.blue, - show: true, +final LineTouchData lineTouchData1 = LineTouchData( + touchCallback: lineTouchCallback, + getTouchedSpotIndicator: getTouchedSpotIndicator, + handleBuiltInTouches: false, + touchSpotThreshold: 12, + touchTooltipData: lineTouchTooltipData1, ); -final BackgroundBarChartRodData backgroundBarChartRodData1Clone = - BackgroundBarChartRodData( - toY: 21, - color: Colors.blue, - show: true, +final LineTouchData lineTouchData1Clone = LineTouchData( + touchCallback: lineTouchCallback, + getTouchedSpotIndicator: getTouchedSpotIndicator, + handleBuiltInTouches: false, + touchSpotThreshold: 12, + touchTooltipData: lineTouchTooltipData1, ); -final BackgroundBarChartRodData backgroundBarChartRodData2 = - BackgroundBarChartRodData( - toY: 44, - color: Colors.red, - show: true, +final LineTouchData lineTouchData2 = LineTouchData( + getTouchedSpotIndicator: getTouchedSpotIndicator, + handleBuiltInTouches: false, + touchSpotThreshold: 12, + touchTooltipData: lineTouchTooltipData1, ); -final BackgroundBarChartRodData backgroundBarChartRodData3 = - BackgroundBarChartRodData( - toY: 44, - color: Colors.green, - show: true, +final LineTouchData lineTouchData3 = LineTouchData( + touchCallback: lineTouchCallback, + handleBuiltInTouches: false, + touchSpotThreshold: 12, + touchTooltipData: lineTouchTooltipData1, ); -final BarChartRodData barChartRodData1 = BarChartRodData( - color: Colors.red, - toY: 12, - width: 32, - borderRadius: const BorderRadius.all(Radius.circular(12)), - rodStackItems: [ - barChartRodStackItem1, - barChartRodStackItem2, - barChartRodStackItem3, - barChartRodStackItem4, - ], - backDrawRodData: backgroundBarChartRodData1, +final LineTouchData lineTouchData5 = LineTouchData( + touchCallback: lineTouchCallback, + getTouchedSpotIndicator: getTouchedSpotIndicator, + handleBuiltInTouches: false, + touchSpotThreshold: 12.001, + touchTooltipData: lineTouchTooltipData1, ); - -final BarChartRodData barChartRodData1Clone = barChartRodData1.copyWith( - rodStackItems: [ - barChartRodStackItem1Clone, - barChartRodStackItem2, - barChartRodStackItem3, - barChartRodStackItem4, - ], +final LineTouchData lineTouchData6 = LineTouchData( + touchCallback: lineTouchCallback, + getTouchedSpotIndicator: getTouchedSpotIndicator, + touchSpotThreshold: 12, + touchTooltipData: lineTouchTooltipData1, ); - -final BarChartRodData barChartRodData2 = BarChartRodData( - color: Colors.red, - toY: 1132, - width: 32, - borderRadius: const BorderRadius.all(Radius.circular(12)), - rodStackItems: [ - barChartRodStackItem1, - barChartRodStackItem2, - barChartRodStackItem3, - barChartRodStackItem4, - ], - backDrawRodData: backgroundBarChartRodData1, +final LineTouchData lineTouchData7 = LineTouchData( + touchCallback: lineTouchCallback, + getTouchedSpotIndicator: getTouchedSpotIndicator, + handleBuiltInTouches: false, + touchSpotThreshold: 12, + touchTooltipData: lineTouchTooltipData1, + getTouchLineEnd: (barData, index) => double.infinity, ); -final BarChartRodData barChartRodData3 = BarChartRodData( - color: Colors.green, - toY: 12, - width: 32, - borderRadius: const BorderRadius.all(Radius.circular(12)), - rodStackItems: [ - barChartRodStackItem2, - ], - backDrawRodData: backgroundBarChartRodData1, +final LineTouchData lineTouchData8 = LineTouchData( + touchCallback: lineTouchCallback, + getTouchedSpotIndicator: getTouchedSpotIndicator, + handleBuiltInTouches: false, + touchSpotThreshold: 12, + touchTooltipData: lineTouchTooltipData1, + longPressDuration: Duration.zero, ); -final BarChartRodData barChartRodData4 = BarChartRodData( - color: Colors.red, - toY: 12, - width: 32, - borderRadius: const BorderRadius.all(Radius.circular(12)), - rodStackItems: [ - barChartRodStackItem2, - barChartRodStackItem1, - barChartRodStackItem4, - barChartRodStackItem3, +final lineTouchResponse1 = LineTouchResponse( + touchLocation: Offset.zero, + touchChartCoordinate: Offset.zero, + lineBarSpots: [ + lineBarSpot1, + lineBarSpot2, ], - backDrawRodData: backgroundBarChartRodData1, ); -final BarChartRodData barChartRodData5 = BarChartRodData( - color: Colors.red, - toY: 12, - width: 55, - borderRadius: const BorderRadius.all(Radius.circular(12)), - rodStackItems: [ - barChartRodStackItem1, - barChartRodStackItem2, - barChartRodStackItem4, - barChartRodStackItem3, +final lineTouchResponse1Clone = LineTouchResponse( + touchLocation: Offset.zero, + touchChartCoordinate: Offset.zero, + lineBarSpots: [ + lineBarSpot1Clone, + lineBarSpot2, ], - backDrawRodData: backgroundBarChartRodData1, -); -final BarChartRodData barChartRodData6 = BarChartRodData( - color: Colors.red, - toY: 12, - width: 32, - borderRadius: const BorderRadius.all(Radius.circular(12)), - backDrawRodData: backgroundBarChartRodData1, ); -final BarChartRodData barChartRodData7 = BarChartRodData( - color: Colors.red, - toY: 12, - width: 32, - borderRadius: const BorderRadius.all(Radius.circular(12)), - rodStackItems: [ - barChartRodStackItem1, - barChartRodStackItem2, - barChartRodStackItem4, - barChartRodStackItem3, +final lineTouchResponse2 = LineTouchResponse( + touchLocation: Offset.zero, + touchChartCoordinate: Offset.zero, + lineBarSpots: [ + lineBarSpot2, + lineBarSpot1, ], - backDrawRodData: backgroundBarChartRodData2, ); -final BarChartRodData barChartRodData8 = BarChartRodData( - color: Colors.red, - toY: 12, - width: 32, - borderRadius: const BorderRadius.all(Radius.circular(14)), - rodStackItems: [ - barChartRodStackItem1, - barChartRodStackItem2, - barChartRodStackItem4, - barChartRodStackItem3, - ], - backDrawRodData: backgroundBarChartRodData1, +final lineTouchResponse3 = LineTouchResponse( + touchLocation: Offset.zero, + touchChartCoordinate: Offset.zero, + lineBarSpots: [], ); -final BarChartGroupData barChartGroupData1 = BarChartGroupData( - x: 12, - showingTooltipIndicators: [0, 1, 2], - barRods: [ - barChartRodData1, - barChartRodData2, - barChartRodData3, - barChartRodData4, +final lineTouchResponse4 = LineTouchResponse( + touchLocation: Offset.zero, + touchChartCoordinate: Offset.zero, + lineBarSpots: [ + lineBarSpot1, + lineBarSpot2, ], - barsSpace: 23, ); -final BarChartGroupData barChartGroupData1Clone = BarChartGroupData( - x: 12, - showingTooltipIndicators: [0, 1, 2], - barRods: [ - barChartRodData1Clone, - barChartRodData2, - barChartRodData3, - barChartRodData4, +final lineTouchResponse5 = LineTouchResponse( + touchLocation: Offset.zero, + touchChartCoordinate: Offset.zero, + lineBarSpots: [ + lineBarSpot1, + lineBarSpot2, ], - barsSpace: 23, ); -final BarChartGroupData barChartGroupData2 = BarChartGroupData( - x: 13, - showingTooltipIndicators: [0, 1, 2], - barRods: [ - barChartRodData1, - barChartRodData2, - barChartRodData3, - barChartRodData4, - ], - barsSpace: 23, +final LineTouchTooltipData lineTouchTooltipData1 = LineTouchTooltipData( + tooltipPadding: const EdgeInsets.all(0.1), + getTooltipColor: lineChartGetGreenColor, + maxContentWidth: 12, + getTooltipItems: lineChartGetTooltipItems, + fitInsideHorizontally: true, + tooltipBorderRadius: BorderRadius.circular(12), + tooltipMargin: 33, + tooltipBorder: const BorderSide(color: Colors.red), ); -final BarChartGroupData barChartGroupData3 = BarChartGroupData( - x: 12, - showingTooltipIndicators: [0, 1], - barRods: [ - barChartRodData1, - barChartRodData2, - barChartRodData3, - barChartRodData4, - ], - barsSpace: 23, + +final LineTouchTooltipData lineTouchTooltipData1Clone = LineTouchTooltipData( + tooltipPadding: const EdgeInsets.all(0.1), + getTooltipColor: lineChartGetGreenColor, + maxContentWidth: 12, + getTooltipItems: lineChartGetTooltipItems, + fitInsideHorizontally: true, + tooltipBorderRadius: BorderRadius.circular(12), + tooltipMargin: 33, + tooltipBorder: const BorderSide(color: Colors.red), ); -final BarChartGroupData barChartGroupData4 = BarChartGroupData( - x: 12, - showingTooltipIndicators: [0, 1, 2], - barRods: [ - barChartRodData1, - barChartRodData2, - barChartRodData4, - ], - barsSpace: 23, +final LineTouchTooltipData lineTouchTooltipData2 = LineTouchTooltipData( + tooltipPadding: const EdgeInsets.all(0.1), + getTooltipColor: lineChartGetRedColor, + maxContentWidth: 12, + getTooltipItems: lineChartGetTooltipItems, + fitInsideHorizontally: true, + tooltipBorderRadius: BorderRadius.circular(12), + tooltipMargin: 33, + tooltipBorder: const BorderSide(color: Colors.red), ); -final BarChartGroupData barChartGroupData5 = BarChartGroupData( - x: 12, - showingTooltipIndicators: [0, 1, 2], - barsSpace: 23, +final LineTouchTooltipData lineTouchTooltipData3 = LineTouchTooltipData( + tooltipPadding: const EdgeInsets.all(0.2), + getTooltipColor: lineChartGetGreenColor, + maxContentWidth: 12, + getTooltipItems: lineChartGetTooltipItems, + fitInsideHorizontally: true, + tooltipBorderRadius: BorderRadius.circular(12), + tooltipMargin: 33, + tooltipBorder: const BorderSide(color: Colors.red), + tooltipHorizontalAlignment: FLHorizontalAlignment.left, ); -final BarChartGroupData barChartGroupData6 = BarChartGroupData( - x: 12, - showingTooltipIndicators: [0, 1, 2], - barRods: [ - barChartRodData2, - barChartRodData3, - barChartRodData4, - barChartRodData1, - ], - barsSpace: 23, +final LineTouchTooltipData lineTouchTooltipData4 = LineTouchTooltipData( + tooltipPadding: const EdgeInsets.all(0.1), + getTooltipColor: lineChartGetGreenColor, + maxContentWidth: 13, + getTooltipItems: lineChartGetTooltipItems, + fitInsideHorizontally: true, + tooltipBorderRadius: BorderRadius.circular(12), + tooltipMargin: 33, + tooltipBorder: const BorderSide(color: Colors.red), + tooltipHorizontalAlignment: FLHorizontalAlignment.right, ); -final BarChartGroupData barChartGroupData7 = BarChartGroupData( - x: 12, - showingTooltipIndicators: [0, 1, 2], - barRods: [ - barChartRodData1, - barChartRodData2, - barChartRodData3, - barChartRodData4, +final LineTouchTooltipData lineTouchTooltipData5 = LineTouchTooltipData( + tooltipPadding: const EdgeInsets.all(0.1), + getTooltipColor: lineChartGetGreenColor, + maxContentWidth: 12, + getTooltipItems: lineChartGetTooltipItems, + fitInsideHorizontally: true, + tooltipBorderRadius: BorderRadius.circular(12), + tooltipMargin: 34, + tooltipBorder: const BorderSide(color: Colors.red), + tooltipHorizontalOffset: 10, +); +final LineTouchTooltipData lineTouchTooltipData6 = LineTouchTooltipData( + tooltipPadding: const EdgeInsets.all(0.1), + getTooltipColor: lineChartGetGreenColor, + maxContentWidth: 12, + getTooltipItems: lineChartGetTooltipItems, + fitInsideHorizontally: true, + tooltipBorderRadius: BorderRadius.circular(12), + tooltipMargin: 33, + tooltipBorder: const BorderSide(color: Colors.pink), + tooltipHorizontalAlignment: FLHorizontalAlignment.left, + tooltipHorizontalOffset: -10, +); + +final LineTouchTooltipData lineTouchTooltipData7 = LineTouchTooltipData( + tooltipPadding: const EdgeInsets.all(0.1), + getTooltipColor: lineChartGetGreenColor, + maxContentWidth: 12, + getTooltipItems: lineChartGetTooltipItems, + fitInsideHorizontally: true, + tooltipBorderRadius: BorderRadius.circular(12), + tooltipMargin: 33, + tooltipBorder: const BorderSide(color: Colors.red, width: 2), + tooltipHorizontalAlignment: FLHorizontalAlignment.right, + tooltipHorizontalOffset: 10, +); + +final FlSpot nullSpot2 = nullSpot1.copyWith(); + +final PieChartData pieChartData1 = PieChartData( + borderData: FlBorderData(show: false, border: Border.all()), + startDegreeOffset: 0, + sections: [ + PieChartSectionData(value: 12, color: Colors.red), + PieChartSectionData(value: 22, color: Colors.green), ], - barsSpace: 44, + centerSpaceColor: Colors.white, + centerSpaceRadius: 12, + pieTouchData: PieTouchData( + enabled: false, + ), + sectionsSpace: 44, + titleSunbeamLayout: false, ); -final BarChartGroupData barChartGroupData8 = BarChartGroupData( - x: 12, - barRods: [ - barChartRodData1, - barChartRodData2, - barChartRodData3, - barChartRodData4, + +final PieChartData pieChartData1Clone = pieChartData1.copyWith(); +final RadarChartData radarChartData1 = RadarChartData( + dataSets: [radarDataSet1], + radarBackgroundColor: Colors.yellow, + radarBorderData: const BorderSide(color: Colors.purple, width: 5), + borderData: borderData1, + gridBorderData: const BorderSide(color: Colors.blue, width: 2), + getTitle: (index, angle) => RadarChartTitle(text: 'testTitle', angle: angle), + titlePositionPercentageOffset: 0.2, + titleTextStyle: const TextStyle(color: Colors.white, fontSize: 12), + radarTouchData: radarTouchData1, + tickCount: 5, + tickBorderData: const BorderSide(width: 4), + ticksTextStyle: const TextStyle(color: Colors.white, fontSize: 12), +); +final RadarChartData radarChartData1Clone = radarChartData1.copyWith(); +final RadarChartData radarChartData2 = RadarChartData( + dataSets: [radarDataSet2], + radarBackgroundColor: Colors.blue, + radarBorderData: const BorderSide(color: Colors.pink, width: 3), + borderData: borderData1, + gridBorderData: const BorderSide(color: Colors.red, width: 3), + getTitle: (index, angle) => RadarChartTitle(text: 'testTitle2', angle: angle), + titlePositionPercentageOffset: 0.5, + titleTextStyle: const TextStyle(color: Colors.black, fontSize: 5), + radarTouchData: radarTouchData2, + tickCount: 1, + tickBorderData: const BorderSide(color: Colors.pink, width: 2), + ticksTextStyle: const TextStyle(color: Colors.purple, fontSize: 10), +); +final RadarDataSet radarDataSet1 = RadarDataSet( + dataEntries: const [ + RadarEntry(value: 0), + RadarEntry(value: 1), + RadarEntry(value: 2), + RadarEntry(value: 3), + RadarEntry(value: 4), ], - barsSpace: 23, + borderColor: Colors.blue, + borderWidth: 3, + entryRadius: 3, + fillColor: Colors.grey, ); -final BarChartGroupData barChartGroupData9 = BarChartGroupData( - x: 12, - showingTooltipIndicators: [0, 1, 2], - barRods: [ - barChartRodData1, - barChartRodData2, - barChartRodData3, - barChartRodData4, +final RadarDataSet radarDataSet1Clone = radarDataSet1.copyWith(); +final RadarDataSet radarDataSet2 = RadarDataSet( + dataEntries: const [ + RadarEntry(value: 10), + RadarEntry(value: 9), + RadarEntry(value: 8), + RadarEntry(value: 7), + RadarEntry(value: 6), ], - barsSpace: 0, + borderColor: Colors.red, + borderWidth: 5, + entryRadius: 5, + fillColor: Colors.black, ); - -final BarTouchedSpot barTouchedSpot1 = BarTouchedSpot( - barChartGroupData1, - 1, - barChartRodData1, - 2, - barChartRodStackItem1, - 1, +final RadarTouchData radarTouchData1 = RadarTouchData( + enabled: true, + touchCallback: radarTouchCallback, + touchSpotThreshold: 12, +); +final RadarTouchData radarTouchData1Clone = radarTouchData1; +final RadarTouchData radarTouchData2 = RadarTouchData( + enabled: false, + touchCallback: radarTouchCallback, + touchSpotThreshold: 5, +); +final radarTouchedSpot1 = RadarTouchedSpot( + radarDataSet1, + 0, + radarDataSet1.dataEntries.first, + 0, flSpot1, Offset.zero, ); -final BarTouchedSpot barTouchedSpot1Clone = BarTouchedSpot( - barChartGroupData1Clone, - 1, - barChartRodData1Clone, - 2, - barChartRodStackItem1Clone, - 1, - flSpot1Clone, +final radarTouchedSpot2 = RadarTouchedSpot( + radarDataSet2, + 0, + radarDataSet1.dataEntries.first, + 0, + flSpot1, Offset.zero, ); -final BarTouchedSpot barTouchedSpot2 = BarTouchedSpot( - barChartGroupData2, + +final radarTouchedSpot3 = RadarTouchedSpot( + radarDataSet1, 1, - barChartRodData1, - 2, - barChartRodStackItem2, - 2, + radarDataSet1.dataEntries.first, + 0, flSpot1, Offset.zero, ); -final BarTouchedSpot barTouchedSpot3 = BarTouchedSpot( - barChartGroupData1, - 1, - barChartRodData2, - 2, - barChartRodStackItem2, - 2, - flSpot1, - Offset.zero, -); -final BarTouchedSpot barTouchedSpot4 = BarTouchedSpot( - barChartGroupData1, - 2, - barChartRodData1, - 2, - barChartRodStackItem2, - 2, + +final radarTouchedSpot4 = RadarTouchedSpot( + radarDataSet1, + 0, + radarDataSet1.dataEntries.last, + 0, flSpot1, Offset.zero, ); -final BarTouchedSpot barTouchedSpot5 = BarTouchedSpot( - barChartGroupData1, + +final radarTouchedSpot5 = RadarTouchedSpot( + radarDataSet1, + 0, + radarDataSet1.dataEntries.first, 1, - barChartRodData1, - 3, - barChartRodStackItem2, - 2, flSpot1, Offset.zero, ); -final BarTouchedSpot barTouchedSpot6 = BarTouchedSpot( - barChartGroupData1, - 1, - barChartRodData1, - 2, - barChartRodStackItem2, - 2, +final radarTouchedSpot6 = RadarTouchedSpot( + radarDataSet1, + 0, + radarDataSet1.dataEntries.first, + 0, flSpot2, Offset.zero, ); -final BarTouchedSpot barTouchedSpot7 = BarTouchedSpot( - barChartGroupData1, - 1, - barChartRodData1, - 2, - barChartRodStackItem2, - 2, +final radarTouchedSpot7 = RadarTouchedSpot( + radarDataSet1, + 0, + radarDataSet1.dataEntries.first, + 0, flSpot1, - const Offset(1, 10), + const Offset(3, 5), ); - -final barTouchResponse1 = BarTouchResponse( - touchLocation: Offset.zero, - touchChartCoordinate: Offset.zero, - spot: barTouchedSpot1, +final RadarTouchedSpot radarTouchedSpotClone1 = radarTouchedSpot1; +final RangeAnnotations rangeAnnotations1 = RangeAnnotations( + horizontalRangeAnnotations: [ + horizontalRangeAnnotation1, + horizontalRangeAnnotation1Clone, + ], + verticalRangeAnnotations: [ + verticalRangeAnnotation1, + verticalRangeAnnotation1Clone, + ], ); -final barTouchResponse1Clone = BarTouchResponse( - touchLocation: Offset.zero, - touchChartCoordinate: Offset.zero, - spot: barTouchedSpot1Clone, +final RangeAnnotations rangeAnnotations1Clone = RangeAnnotations( + horizontalRangeAnnotations: [ + horizontalRangeAnnotation1, + horizontalRangeAnnotation1Clone, + ], + verticalRangeAnnotations: [ + verticalRangeAnnotation1, + verticalRangeAnnotation1Clone, + ], ); -final barTouchResponse2 = BarTouchResponse( - touchLocation: Offset.zero, - touchChartCoordinate: Offset.zero, - spot: barTouchedSpot2, +final RangeAnnotations rangeAnnotations2 = RangeAnnotations( + horizontalRangeAnnotations: [ + horizontalRangeAnnotation1Clone, + ], + verticalRangeAnnotations: [ + verticalRangeAnnotation1, + verticalRangeAnnotation1Clone, + ], +); +final ScatterChartData scatterChartData1 = ScatterChartData( + minY: 0, + maxY: 12, + maxX: 22, + minX: 11, + gridData: const FlGridData( + show: false, + getDrawingHorizontalLine: gridGetDrawingLine, + getDrawingVerticalLine: gridGetDrawingLine, + checkToShowHorizontalLine: gridCheckToShowLine, + checkToShowVerticalLine: gridCheckToShowLine, + drawVerticalLine: false, + horizontalInterval: 33, + verticalInterval: 1, + ), + backgroundColor: Colors.black, + clipData: const FlClipData.none(), + borderData: FlBorderData( + show: true, + border: Border.all( + color: Colors.white, + ), + ), + scatterSpots: [ + ScatterSpot( + 0, + 0, + show: false, + dotPainter: FlDotCirclePainter(radius: 33, color: Colors.yellow), + ), + ScatterSpot( + 2, + 2, + show: false, + renderPriority: 10, + dotPainter: FlDotCirclePainter(radius: 11, color: Colors.purple), + ), + ScatterSpot( + 1, + 2, + show: false, + renderPriority: -1, + dotPainter: FlDotCirclePainter(radius: 11, color: Colors.white), + ), + ], + scatterTouchData: ScatterTouchData( + enabled: true, + touchTooltipData: ScatterTouchTooltipData( + getTooltipItems: scatterChartGetTooltipItems, + fitInsideHorizontally: true, + fitInsideVertically: false, + maxContentWidth: 33, + getTooltipColor: (touchedSpot) => Colors.white, + tooltipPadding: const EdgeInsets.all(23), + tooltipBorderRadius: BorderRadius.circular(534), + ), + handleBuiltInTouches: false, + touchCallback: scatterTouchCallback, + touchSpotThreshold: 12, + ), + showingTooltipIndicators: [0, 1, 2], + titlesData: const FlTitlesData( + leftTitles: AxisTitles( + axisNameSize: 33, + axisNameWidget: MockData.widget1, + ), + rightTitles: AxisTitles( + axisNameSize: 1326, + axisNameWidget: MockData.widget3, + sideTitles: SideTitles(reservedSize: 500, showTitles: true), + ), + topTitles: AxisTitles( + axisNameSize: 34, + axisNameWidget: MockData.widget4, + ), + bottomTitles: AxisTitles( + axisNameSize: 22, + axisNameWidget: MockData.widget2, + ), + ), + scatterLabelSettings: ScatterLabelSettings( + showLabel: true, + getLabelTextStyleFunction: getLabelTextStyle, + getLabelFunction: getLabel, + ), ); +final ScatterChartData scatterChartData1Clone = scatterChartData1.copyWith(); +final ScatterSpot scatterSpot1 = ScatterSpot(1, 40); +final ScatterSpot scatterSpot1Clone = ScatterSpot(1, 40); -final BarTooltipItem barTooltipItem1 = BarTooltipItem( - 'pashmam 1', - const TextStyle(color: Colors.red), +final ScatterSpot scatterSpot2 = ScatterSpot(-4, -8); +final ScatterSpot scatterSpot2Clone = scatterSpot2.copyWith(); + +final ScatterSpot scatterSpot3 = ScatterSpot(-14, 5); +final ScatterSpot scatterSpot4 = ScatterSpot(-0, 0); +final scatterTouchTooltipData1 = ScatterTouchTooltipData( + tooltipBorderRadius: BorderRadius.circular(23), + tooltipPadding: const EdgeInsets.all(11), + getTooltipColor: scatterChartGetTooltipGreenColor, + maxContentWidth: 33, + fitInsideVertically: true, + fitInsideHorizontally: false, + getTooltipItems: scatterChartGetTooltipItems, + tooltipBorder: const BorderSide(color: Colors.red), ); -final BarTooltipItem barTooltipItem1Clone = BarTooltipItem( - 'pashmam 1', - const TextStyle(color: Colors.red), +final scatterTouchTooltipData1Clone = ScatterTouchTooltipData( + tooltipBorderRadius: BorderRadius.circular(23), + tooltipPadding: const EdgeInsets.all(11), + getTooltipColor: scatterChartGetTooltipGreenColor, + maxContentWidth: 33, + fitInsideVertically: true, + fitInsideHorizontally: false, + getTooltipItems: scatterChartGetTooltipItems, + tooltipBorder: const BorderSide(color: Colors.red), ); -final BarTooltipItem barTooltipItem2 = BarTooltipItem( - 'pashmam 2', - const TextStyle(color: Colors.red), +final scatterTouchTooltipData2 = ScatterTouchTooltipData( + tooltipBorderRadius: BorderRadius.circular(23), + tooltipPadding: const EdgeInsets.all(11), + getTooltipColor: scatterChartGetTooltipGreenColor, + maxContentWidth: 33, + fitInsideVertically: true, + fitInsideHorizontally: false, + getTooltipItems: scatterChartGetTooltipItems, + tooltipBorder: const BorderSide(color: Colors.blue), + tooltipHorizontalAlignment: FLHorizontalAlignment.left, ); -final BarTooltipItem barTooltipItem3 = BarTooltipItem( - 'pashmam 1', - const TextStyle(color: Colors.green), +final scatterTouchTooltipData3 = ScatterTouchTooltipData( + tooltipBorderRadius: BorderRadius.circular(23), + tooltipPadding: const EdgeInsets.all(11), + getTooltipColor: scatterChartGetTooltipGreenColor, + maxContentWidth: 33, + fitInsideVertically: true, + fitInsideHorizontally: false, + getTooltipItems: scatterChartGetTooltipItems, + tooltipBorder: const BorderSide(color: Colors.red, width: 2), + tooltipHorizontalAlignment: FLHorizontalAlignment.right, + tooltipHorizontalOffset: 10, ); -final BarTooltipItem barTooltipItem4 = BarTooltipItem( - 'null', - const TextStyle(color: Colors.red), +final Shadow shadow4 = Shadow( + color: Colors.red.withValues(alpha: 0.5), + blurRadius: 12, ); -final BarTooltipItem barTooltipItem5 = BarTooltipItem( - 'pashmam 1', - const TextStyle(fontSize: 85), +final ShowingTooltipIndicators showingTooltipIndicator1 = + ShowingTooltipIndicators( + [lineBarSpot1, lineBarSpot2], ); - -BarTooltipItem getTooltipItem( - BarChartGroupData group, - int groupIndex, - BarChartRodData rod, - int rodIndex, -) { - const textStyle = TextStyle( - color: Colors.black, - fontWeight: FontWeight.bold, - fontSize: 14, - ); - return BarTooltipItem(rod.toY.toString(), textStyle); -} - -Color getTooltipGreenColor( - BarChartGroupData group, -) { - return Colors.green; -} - -Color getTooltipBlueColor( - BarChartGroupData group, -) { - return Colors.blue; -} - -final BarTouchTooltipData barTouchTooltipData1 = BarTouchTooltipData( - tooltipBorderRadius: BorderRadius.circular(12), - fitInsideVertically: false, - fitInsideHorizontally: true, - maxContentWidth: 23, - getTooltipColor: getTooltipGreenColor, - tooltipPadding: const EdgeInsets.all(23), - getTooltipItem: getTooltipItem, - tooltipMargin: 12, - tooltipBorder: const BorderSide(color: Colors.red), -); -final BarTouchTooltipData barTouchTooltipData1Clone = BarTouchTooltipData( - tooltipBorderRadius: BorderRadius.circular(12), - fitInsideVertically: false, - fitInsideHorizontally: true, - maxContentWidth: 23, - getTooltipColor: getTooltipGreenColor, - tooltipPadding: const EdgeInsets.all(23), - getTooltipItem: getTooltipItem, - tooltipMargin: 12, - tooltipBorder: const BorderSide(color: Colors.red), +final ShowingTooltipIndicators showingTooltipIndicator1Clone = + ShowingTooltipIndicators( + [lineBarSpot1, lineBarSpot2], ); -final BarTouchTooltipData barTouchTooltipData2 = BarTouchTooltipData( - tooltipBorderRadius: BorderRadius.circular(13), - fitInsideVertically: false, - fitInsideHorizontally: true, - maxContentWidth: 23, - getTooltipColor: getTooltipGreenColor, - tooltipPadding: const EdgeInsets.all(23), - getTooltipItem: getTooltipItem, - tooltipMargin: 12, - tooltipBorder: const BorderSide(color: Colors.red), - tooltipHorizontalAlignment: FLHorizontalAlignment.center, +final ShowingTooltipIndicators showingTooltipIndicator3 = + ShowingTooltipIndicators( + [lineBarSpot2], ); -final BarTouchTooltipData barTouchTooltipData3 = BarTouchTooltipData( - tooltipBorderRadius: BorderRadius.circular(12), - fitInsideVertically: true, - fitInsideHorizontally: true, - maxContentWidth: 23, - getTooltipColor: getTooltipGreenColor, - tooltipPadding: const EdgeInsets.all(23), - getTooltipItem: getTooltipItem, - tooltipMargin: 12, - tooltipBorder: const BorderSide(color: Colors.red), - tooltipHorizontalAlignment: FLHorizontalAlignment.left, +final ShowingTooltipIndicators showingTooltipIndicator4 = + ShowingTooltipIndicators( + [lineBarSpot2, lineBarSpot1], ); -final BarTouchTooltipData barTouchTooltipData4 = BarTouchTooltipData( - tooltipBorderRadius: BorderRadius.circular(12), - fitInsideVertically: false, - fitInsideHorizontally: false, - maxContentWidth: 23, - getTooltipColor: getTooltipGreenColor, - tooltipPadding: const EdgeInsets.all(23), - getTooltipItem: getTooltipItem, - tooltipMargin: 12, - tooltipBorder: const BorderSide(color: Colors.red), - tooltipHorizontalAlignment: FLHorizontalAlignment.right, +final ShowingTooltipIndicators showingTooltipIndicator5 = + ShowingTooltipIndicators( + [lineBarSpot1, lineBarSpot2, lineBarSpot2], ); -final BarTouchTooltipData barTouchTooltipData5 = BarTouchTooltipData( - tooltipBorderRadius: BorderRadius.circular(12), - fitInsideVertically: false, - fitInsideHorizontally: true, - maxContentWidth: 23.00001, - getTooltipColor: getTooltipGreenColor, - tooltipPadding: const EdgeInsets.all(23), - getTooltipItem: getTooltipItem, - tooltipMargin: 12, - tooltipBorder: const BorderSide(color: Colors.red), - tooltipHorizontalAlignment: FLHorizontalAlignment.center, - tooltipHorizontalOffset: 10, +final SizedPicture sizedPicture1 = SizedPicture( + PictureRecorder().endRecording(), + 10, + 30, ); -final BarTouchTooltipData barTouchTooltipData6 = BarTouchTooltipData( - tooltipBorderRadius: BorderRadius.circular(12), - fitInsideVertically: false, - fitInsideHorizontally: true, - maxContentWidth: 23, - getTooltipColor: getTooltipBlueColor, - tooltipPadding: const EdgeInsets.all(23), - getTooltipItem: getTooltipItem, - tooltipMargin: 12, - tooltipBorder: const BorderSide(color: Colors.red), - tooltipHorizontalAlignment: FLHorizontalAlignment.left, - tooltipHorizontalOffset: -10, +final SizedPicture sizedPicture1Clone = SizedPicture( + PictureRecorder().endRecording(), + 10, + 30, ); -final BarTouchTooltipData barTouchTooltipData7 = BarTouchTooltipData( - tooltipBorderRadius: BorderRadius.circular(12), - fitInsideVertically: false, - fitInsideHorizontally: true, - maxContentWidth: 23, - getTooltipColor: getTooltipGreenColor, - getTooltipItem: getTooltipItem, - tooltipMargin: 12, - tooltipBorder: const BorderSide(color: Colors.red), - tooltipHorizontalAlignment: FLHorizontalAlignment.right, - tooltipHorizontalOffset: 10, + +final SizedPicture sizedPicture2 = SizedPicture( + PictureRecorder().endRecording(), + 11, + 30, ); -final BarTouchTooltipData barTouchTooltipData8 = BarTouchTooltipData( - tooltipBorderRadius: BorderRadius.circular(12), - fitInsideVertically: false, - fitInsideHorizontally: true, - maxContentWidth: 23, - getTooltipColor: getTooltipGreenColor, - tooltipPadding: const EdgeInsets.all(23), - tooltipMargin: 12, - tooltipBorder: const BorderSide(color: Colors.red), + +final SizedPicture sizedPicture3 = SizedPicture( + PictureRecorder().endRecording(), + 10, + 32, ); -final BarTouchTooltipData barTouchTooltipData9 = BarTouchTooltipData( - tooltipBorderRadius: BorderRadius.circular(12), - fitInsideVertically: false, - fitInsideHorizontally: true, - maxContentWidth: 23, - getTooltipColor: getTooltipGreenColor, - tooltipPadding: const EdgeInsets.all(23), - getTooltipItem: getTooltipItem, - tooltipMargin: 333, - tooltipBorder: const BorderSide(color: Colors.red), + +final SizedPicture sizedPicture4 = SizedPicture( + PictureRecorder().endRecording(), + 442, + 30, ); -final BarTouchTooltipData barTouchTooltipData10 = BarTouchTooltipData( - tooltipBorderRadius: BorderRadius.circular(12), - fitInsideVertically: false, - fitInsideHorizontally: true, - maxContentWidth: 23, - getTooltipColor: getTooltipGreenColor, - tooltipPadding: const EdgeInsets.all(23), - getTooltipItem: getTooltipItem, - tooltipMargin: 12, - tooltipBorder: const BorderSide(color: Colors.blue), + +final VerticalLine verticalLine1 = VerticalLine( + x: 12, + color: Colors.red, + dashArray: [0, 1], + strokeWidth: 21, + label: verticalLineLabel1, ); -final BarTouchTooltipData barTouchTooltipData11 = BarTouchTooltipData( - tooltipBorderRadius: BorderRadius.circular(12), - fitInsideVertically: false, - fitInsideHorizontally: true, - maxContentWidth: 23, - getTooltipColor: getTooltipGreenColor, - tooltipPadding: const EdgeInsets.all(23), - getTooltipItem: getTooltipItem, - tooltipMargin: 12, - tooltipBorder: const BorderSide(color: Colors.red, width: 2), + +final VerticalLine verticalLine1Clone = VerticalLine( + x: 12, + color: Colors.red, + dashArray: [0, 1], + strokeWidth: 21, + label: verticalLineLabel1, ); -void barTouchCallback(FlTouchEvent event, BarTouchResponse? response) {} +final VerticalLine verticalLine2 = VerticalLine( + x: 12, + color: Colors.green, + dashArray: [0, 1], + strokeWidth: 21, + label: verticalLineLabel1, +); -void scatterTouchCallback(FlTouchEvent event, ScatterTouchResponse? response) {} +final VerticalLine verticalLine3 = VerticalLine( + x: 12, + color: Colors.red, + dashArray: [0, 1], + strokeWidth: 22, + label: verticalLineLabel1, +); -final BarTouchData barTouchData1 = BarTouchData( - touchTooltipData: barTouchTooltipData1, - handleBuiltInTouches: false, - touchCallback: barTouchCallback, - enabled: false, - allowTouchBarBackDraw: true, - touchExtraThreshold: const EdgeInsets.all(12), +final VerticalLine verticalLine4 = VerticalLine( + x: 12, + color: Colors.red, + dashArray: [1, 0], + strokeWidth: 21, + label: verticalLineLabel1, ); -final BarTouchData barTouchData1Clone = BarTouchData( - touchTooltipData: barTouchTooltipData1Clone, - handleBuiltInTouches: false, - touchCallback: barTouchCallback, - enabled: false, - allowTouchBarBackDraw: true, - touchExtraThreshold: const EdgeInsets.all(12), + +final VerticalLine verticalLine5 = VerticalLine( + x: 33, + color: Colors.red, + dashArray: [0, 1], + strokeWidth: 21, + label: verticalLineLabel1, ); -const BarTouchData barTouchData2 = BarTouchData( - handleBuiltInTouches: false, - touchCallback: barTouchCallback, - enabled: false, - allowTouchBarBackDraw: true, - touchExtraThreshold: EdgeInsets.all(12), + +final VerticalLine verticalLine6 = VerticalLine( + x: 12, + color: Colors.green, + dashArray: [0, 1], + strokeWidth: 21, + label: verticalLineLabel1, ); -final BarTouchData barTouchData3 = BarTouchData( - touchTooltipData: barTouchTooltipData1, - handleBuiltInTouches: true, - touchCallback: barTouchCallback, - enabled: false, - allowTouchBarBackDraw: true, - touchExtraThreshold: const EdgeInsets.all(12), + +final VerticalLine verticalLine7 = VerticalLine( + x: 12, + color: Colors.red, + dashArray: [0, 1], + strokeWidth: 21, + label: verticalLineLabel2, ); -final BarTouchData barTouchData4 = BarTouchData( - touchTooltipData: barTouchTooltipData2, - handleBuiltInTouches: false, - touchCallback: barTouchCallback, - enabled: false, - allowTouchBarBackDraw: true, - touchExtraThreshold: const EdgeInsets.all(12), + +final VerticalLine verticalLine8 = VerticalLine( + x: 12, + color: Colors.red, + strokeWidth: 21, + label: verticalLineLabel1, ); -final BarTouchData barTouchData5 = BarTouchData( - touchTooltipData: barTouchTooltipData1, - handleBuiltInTouches: false, - enabled: false, - allowTouchBarBackDraw: true, - touchExtraThreshold: const EdgeInsets.all(12), + +final VerticalLine verticalLine9 = VerticalLine( + x: 12, + color: Colors.red, + dashArray: [0, 12, 44], + strokeWidth: 21, + label: verticalLineLabel1, ); -final BarTouchData barTouchData6 = BarTouchData( - touchTooltipData: barTouchTooltipData1, - handleBuiltInTouches: false, - touchCallback: barTouchCallback, - enabled: true, - allowTouchBarBackDraw: true, - touchExtraThreshold: const EdgeInsets.all(12), + +final VerticalLineLabel verticalLineLabel1 = VerticalLineLabel( + show: true, + style: const TextStyle(color: Colors.green), + labelResolver: verticalLabelResolver, + alignment: Alignment.topCenter, + padding: const EdgeInsets.all(12), ); -final BarTouchData barTouchData7 = BarTouchData( - touchTooltipData: barTouchTooltipData1, - handleBuiltInTouches: false, - touchCallback: barTouchCallback, - enabled: false, - allowTouchBarBackDraw: false, - touchExtraThreshold: const EdgeInsets.all(12), + +final VerticalLineLabel verticalLineLabel1Clone = VerticalLineLabel( + show: true, + style: const TextStyle(color: Colors.green), + labelResolver: verticalLabelResolver, + alignment: Alignment.topCenter, + padding: const EdgeInsets.all(12), ); -final BarTouchData barTouchData8 = BarTouchData( - touchTooltipData: barTouchTooltipData1, - handleBuiltInTouches: false, - touchCallback: barTouchCallback, - enabled: false, - allowTouchBarBackDraw: true, + +final VerticalLineLabel verticalLineLabel2 = VerticalLineLabel( + style: const TextStyle(color: Colors.green), + labelResolver: verticalLabelResolver, + alignment: Alignment.topCenter, + padding: const EdgeInsets.all(12), ); -final BarTouchData barTouchData9 = BarTouchData( - touchTooltipData: barTouchTooltipData1, - handleBuiltInTouches: false, - touchCallback: barTouchCallback, - enabled: false, - allowTouchBarBackDraw: true, - touchExtraThreshold: const EdgeInsets.only(left: 12), + +final VerticalLineLabel verticalLineLabel3 = VerticalLineLabel( + show: true, + labelResolver: verticalLabelResolver, + alignment: Alignment.topCenter, + padding: const EdgeInsets.all(12), ); -final BarTouchData barTouchData10 = BarTouchData( - touchTooltipData: barTouchTooltipData1, - handleBuiltInTouches: false, - touchCallback: barTouchCallback, - enabled: false, - allowTouchBarBackDraw: true, - touchExtraThreshold: const EdgeInsets.all(12), - longPressDuration: Duration.zero, + +final VerticalLineLabel verticalLineLabel4 = VerticalLineLabel( + show: true, + style: const TextStyle(color: Colors.green), + alignment: Alignment.topCenter, + padding: const EdgeInsets.all(12), +); + +final VerticalLineLabel verticalLineLabel5 = VerticalLineLabel( + show: true, + style: const TextStyle(color: Colors.green), + labelResolver: verticalLabelResolver, + padding: const EdgeInsets.all(12), +); +final VerticalLineLabel verticalLineLabel6 = VerticalLineLabel( + show: true, + style: const TextStyle(color: Colors.green), + labelResolver: verticalLabelResolver, + alignment: Alignment.topCenter, + padding: const EdgeInsets.all(44), ); +final VerticalLineLabel verticalLineLabel7 = VerticalLineLabel( + style: const TextStyle(color: Colors.green), + labelResolver: verticalLabelResolver, + alignment: Alignment.topCenter, + padding: const EdgeInsets.all(12), + direction: LabelDirection.vertical, +); +final VerticalRangeAnnotation verticalRangeAnnotation1 = + VerticalRangeAnnotation(color: Colors.green, x2: 12, x1: 12.1); +final VerticalRangeAnnotation verticalRangeAnnotation1Clone = + VerticalRangeAnnotation(color: Colors.green, x2: 12, x1: 12.1); + +void barTouchCallback(FlTouchEvent event, BarTouchResponse? response) {} +Color candlestickChartGetTooltipGreenColor(CandlestickSpot spots) => + Colors.green; + +CandlestickTooltipItem? candlestickChartGetTooltipItems( + FlCandlestickPainter painter, + CandlestickSpot touchedSpot, + int spotIndex, +) { + return CandlestickTooltipItem( + 'check', + textStyle: const TextStyle(color: Colors.blue), + bottomMargin: 23, + ); +} + +Color candlestickChartGetTooltipRedColor(CandlestickSpot spots) => Colors.red; + +bool checkToShowDot(FlSpot spot, LineChartBarData barData) => true; + +bool checkToShowLine(double value) => true; + +bool checkToShowSpotLine(FlSpot spot) => true; + +FlDotCirclePainter getDotDrawer( + FlSpot spot, + double percent, + LineChartBarData barData, + int index, +) => + FlDotCirclePainter(radius: 44, strokeWidth: 12); + +FlDotCirclePainter getDotDrawer5( + FlSpot spot, + double percent, + LineChartBarData barData, + int index, +) => + FlDotCirclePainter(radius: 44, strokeWidth: 14); + +FlDotCirclePainter getDotDrawer6( + FlSpot spot, + double percent, + LineChartBarData barData, + int index, +) => + FlDotCirclePainter(radius: 44.01, strokeWidth: 14); + +FlDotCirclePainter getDotDrawerTouched( + FlSpot spot, + double percent, + LineChartBarData barData, + int index, +) => + FlDotCirclePainter(radius: 12, color: Colors.red); + +FlDotCirclePainter getDotDrawerTouched4( + FlSpot spot, + double percent, + LineChartBarData barData, + int index, +) => + FlDotCirclePainter(radius: 12); + +FlDotCirclePainter getDotDrawerTouched6( + FlSpot spot, + double percent, + LineChartBarData barData, + int index, +) => + FlDotCirclePainter(radius: 12.01, color: Colors.red); + +FlLine getDrawingLine(double value) => const FlLine(); + +String getLabel(int spotIndex, ScatterSpot spot) => 'label'; + +TextStyle getLabelTextStyle(int spotIndex, ScatterSpot spot) => + const TextStyle(color: Colors.green); + +TextStyle getTextStyles(BuildContext context, double value) => + const TextStyle(color: Colors.green); + +Widget getTitles(double value, TitleMeta meta) => const Text('sallam'); + +Color getTooltipBlueColor( + BarChartGroupData group, +) { + return Colors.blue; +} + +Color getTooltipGreenColor( + BarChartGroupData group, +) { + return Colors.green; +} + +BarTooltipItem getTooltipItem( + BarChartGroupData group, + int groupIndex, + BarChartRodData rod, + int rodIndex, +) { + const textStyle = TextStyle( + color: Colors.black, + fontWeight: FontWeight.bold, + fontSize: 14, + ); + return BarTooltipItem(rod.toY.toString(), textStyle); +} + +List getTouchedSpotIndicator( + LineChartBarData barData, + List indexes, +) => + indexes.map((i) => touchedSpotIndicatorData1).toList(); +bool gridCheckToShowLine(double value) => true; + +FlLine gridGetDrawingLine(double value) => const FlLine(); + +String horizontalLabelResolver(HorizontalLine horizontalLine) => 'test'; + +Color lineChartGetGreenColor(LineBarSpot touchedSpot) { + return Colors.green; +} + +Color lineChartGetRedColor(LineBarSpot touchedSpot) { + return Colors.red; +} + +List lineChartGetTooltipItems(List list) { + return list.map((s) => lineTooltipItem1).toList(); +} + +void lineTouchCallback(FlTouchEvent event, LineTouchResponse? response) {} + +void radarTouchCallback(FlTouchEvent event, RadarTouchResponse? response) {} + +Color scatterChartGetTooltipGreenColor(ScatterSpot spots) { + return Colors.green; //Color +} + +ScatterTooltipItem? scatterChartGetTooltipItems(ScatterSpot spots) { + return ScatterTooltipItem( + 'check', + textStyle: const TextStyle(color: Colors.blue), + bottomMargin: 23, + ); +} + +Color scatterChartGetTooltipRedColor(ScatterSpot spots) { + return Colors.red; //Color +} + +void scatterTouchCallback(FlTouchEvent event, ScatterTouchResponse? response) {} + +String verticalLabelResolver(VerticalLine horizontalLine) => 'test'; + +class MockData { + static const color0 = Color(0x00000000); + static const color1 = Color(0x11111111); + static const color2 = Color(0x22222222); + static const color3 = Color(0x33333333); + static const color4 = Color(0x44444444); + static const color5 = Color(0x55555555); + static const color6 = Color(0x66666666); + + static final path1 = Path() + ..moveTo(10, 10) + ..lineTo(20, 20) + ..arcTo( + Rect.fromCenter(center: Offset.zero, width: 44, height: 22), + 2, + 3, + false, + ); + + static final path1Duplicate = Path() + ..moveTo(10, 10) + ..lineTo(20, 20) + ..arcTo( + Rect.fromCenter(center: Offset.zero, width: 44, height: 22), + 2, + 3, + false, + ); + + static final path2 = Path() + ..moveTo(10, 10) + ..lineTo(20, 20) + ..arcTo( + Rect.fromCenter(center: Offset.zero, width: 44, height: 22.01), + 2, + 3, + false, + ); + + static final path3 = Path() + ..moveTo(10, 13) + ..lineTo(20, 20) + ..arcTo( + Rect.fromCenter(center: Offset.zero, width: 44, height: 22), + 2, + 3, + false, + ); + + static final path4 = Path() + ..moveTo(24, 13) + ..lineTo(20, 20) + ..arcTo( + Rect.fromCenter(center: Offset.zero, width: 44, height: 22), + 2, + 3, + false, + ); + + static const borderSide1 = BorderSide(color: color1); + static const borderSide2 = BorderSide(color: color2, width: 2); + static const borderSide3 = BorderSide(color: color3, width: 3); + static const borderSide4 = BorderSide(color: color4, width: 4); + static const borderSide5 = BorderSide(color: color5, width: 5); + static const borderSide6 = BorderSide(color: color6, width: 6); + + static const TextStyle textStyle1 = + TextStyle(color: color1, fontWeight: FontWeight.w100); + static const TextStyle textStyle2 = + TextStyle(color: color2, fontWeight: FontWeight.w200); + static const TextStyle textStyle3 = + TextStyle(color: color3, fontWeight: FontWeight.w300); + static const TextStyle textStyle4 = + TextStyle(color: color4, fontWeight: FontWeight.w400); -final BarChartData barChartData1 = BarChartData( - minY: 12, - titlesData: MockData.flTitlesData1, - gridData: flGridData1, - rangeAnnotations: rangeAnnotations1, - maxY: 23, - backgroundColor: Colors.green, - borderData: borderData1, - alignment: BarChartAlignment.spaceAround, - barGroups: [ - barChartGroupData1, - barChartGroupData2, - barChartGroupData3, - ], - barTouchData: barTouchData1, - groupsSpace: 23, - extraLinesData: extraLinesData1, -); -final BarChartData barChartData1Clone = barChartData1.copyWith( - titlesData: MockData.flTitlesData1Clone, - gridData: flGridData1Clone, - borderData: borderData1Clone, - barTouchData: barTouchData1Clone, - rangeAnnotations: rangeAnnotations1Clone, -); + static const Offset offset1 = Offset(1, 1); + static const Offset offset1Duplicate = Offset(1, 1); + static const Offset offset2 = Offset(2, 2); + static const Offset offset3 = Offset(2, 2); + static const Offset offset4 = Offset(4, 4); + static const Offset offset5 = Offset(5, 5); + static const Offset offset6 = Offset(6, 6); -final BarChartData barChartData2 = barChartData1.copyWith( - minY: 11, -); -final BarChartData barChartData3 = barChartData1.copyWith( - titlesData: MockData.flTitlesData2, -); -final BarChartData barChartData4 = barChartData1.copyWith( - gridData: flGridData2, -); -final BarChartData barChartData5 = barChartData1.copyWith( - rangeAnnotations: rangeAnnotations2, -); -final BarChartData barChartData6 = barChartData1.copyWith( - maxY: 52345, -); -final BarChartData barChartData7 = barChartData1.copyWith( - backgroundColor: Colors.red, -); -final BarChartData barChartData8 = barChartData1.copyWith( - titlesData: MockData.flTitlesData3, -); -final BarChartData barChartData9 = barChartData1.copyWith( - borderData: borderData2, -); -final BarChartData barChartData10 = barChartData1.copyWith( - alignment: BarChartAlignment.center, -); -final BarChartData barChartData11 = barChartData1.copyWith( - barGroups: [], -); -final BarChartData barChartData12 = barChartData1.copyWith( - barGroups: [ - barChartGroupData3, - barChartGroupData1, - barChartGroupData2, - ], -); -final BarChartData barChartData13 = barChartData1.copyWith( - barTouchData: barTouchData2, -); -final BarChartData barChartData14 = barChartData1.copyWith( - groupsSpace: 444, -); -final BarChartData barChartData15 = barChartData1.copyWith( - extraLinesData: extraLinesData2, -); + static const size1 = Size(11, 11); + static const size2 = Size(22, 22); -final RadarDataSet radarDataSet1 = RadarDataSet( - dataEntries: const [ - RadarEntry(value: 0), - RadarEntry(value: 1), - RadarEntry(value: 2), - RadarEntry(value: 3), - RadarEntry(value: 4), - ], - borderColor: Colors.blue, - borderWidth: 3, - entryRadius: 3, - fillColor: Colors.grey, -); + static final textPainter1 = TextPainter(); + static final textPainter2 = TextPainter() + ..text = const TextSpan(text: 'test') + ..textDirection = TextDirection.ltr + ..layout(); -final RadarDataSet radarDataSet1Clone = radarDataSet1.copyWith(); + static final rect1 = Rect.fromCenter(center: offset1, width: 11, height: 11); + static final rect2 = Rect.fromCenter(center: offset2, width: 22, height: 22); -final RadarDataSet radarDataSet2 = RadarDataSet( - dataEntries: const [ - RadarEntry(value: 10), - RadarEntry(value: 9), - RadarEntry(value: 8), - RadarEntry(value: 7), - RadarEntry(value: 6), - ], - borderColor: Colors.red, - borderWidth: 5, - entryRadius: 5, - fillColor: Colors.black, -); + static final rRect1 = RRect.fromLTRBR(1, 1, 1, 1, const Radius.circular(11)); + static final rRect2 = RRect.fromLTRBR(2, 2, 2, 2, const Radius.circular(22)); -final RadarTouchData radarTouchData1 = RadarTouchData( - enabled: true, - touchCallback: radarTouchCallback, - touchSpotThreshold: 12, -); + static final paint1 = Paint() + ..color = color1 + ..strokeWidth = 11; + static final paint2 = Paint() + ..color = color2 + ..strokeWidth = 22; -final RadarTouchData radarTouchData2 = RadarTouchData( - enabled: false, - touchCallback: radarTouchCallback, - touchSpotThreshold: 5, -); + static Picture? _picture1; -final RadarTouchData radarTouchData1Clone = radarTouchData1; + static Image? _image1; -void radarTouchCallback(FlTouchEvent event, RadarTouchResponse? response) {} + static final LineChartBarData lineChartBarData1 = LineChartBarData( + dashArray: [0, 1], + gradient: const LinearGradient( + colors: [Colors.red, Colors.green], + stops: [0, 1], + begin: Alignment.center, + end: Alignment.bottomRight, + ), + spots: [ + flSpot1, + flSpot2, + ], + shadow: shadow1, + aboveBarData: barAreaData1, + belowBarData: barAreaData2, + barWidth: 12, + curveSmoothness: 12, + dotData: flDotData1, + isStrokeCapRound: true, + preventCurveOvershootingThreshold: 1.2, + showingIndicators: [0, 1], + ); -final radarTouchedSpot1 = RadarTouchedSpot( - radarDataSet1, - 0, - radarDataSet1.dataEntries.first, - 0, - flSpot1, - Offset.zero, -); + static final LineChartBarData lineChartBarData2 = LineChartBarData( + dashArray: [0, 1], + gradient: const LinearGradient( + colors: [Colors.red, Colors.green], + stops: [0, 1], + begin: Alignment.center, + end: Alignment.bottomRight, + ), + spots: [ + flSpot1, + flSpot2, + ], + shadow: shadow2, + isStepLineChart: true, + aboveBarData: barAreaData1, + belowBarData: barAreaData2, + barWidth: 12, + curveSmoothness: 12, + dotData: flDotData1, + isStrokeCapRound: true, + preventCurveOvershootingThreshold: 1.2, + showingIndicators: [0, 4], + ); -final RadarTouchedSpot radarTouchedSpotClone1 = radarTouchedSpot1; + static const FlSpot flSpot0 = FlSpot.zero; -final radarTouchedSpot2 = RadarTouchedSpot( - radarDataSet2, - 0, - radarDataSet1.dataEntries.first, - 0, - flSpot1, - Offset.zero, -); + static const flSpot1 = FlSpot(1, 1); -final radarTouchedSpot3 = RadarTouchedSpot( - radarDataSet1, - 1, - radarDataSet1.dataEntries.first, - 0, - flSpot1, - Offset.zero, -); + static const flSpot2 = FlSpot(2, 2); + static const flSpot3 = FlSpot(3, 3); + static const flSpot4 = FlSpot(4, 4); + static const flSpot5 = FlSpot(5, 5); + static final horizontalLine0 = HorizontalLine(y: 0, color: color0); + static final horizontalLine1 = HorizontalLine(y: 1, color: color1); -final radarTouchedSpot4 = RadarTouchedSpot( - radarDataSet1, - 0, - radarDataSet1.dataEntries.last, - 0, - flSpot1, - Offset.zero, -); + static final horizontalLine2 = HorizontalLine(y: 2, color: color2); + static final horizontalLine3 = HorizontalLine(y: 3, color: color3); + static final horizontalLine4 = HorizontalLine(y: 4, color: color4); + static final horizontalLine5 = HorizontalLine(y: 5, color: color5); + static final verticalLine0 = VerticalLine(x: 0, color: color0); + static final verticalLine1 = VerticalLine(x: 1, color: color1); + + static final verticalLine2 = VerticalLine(x: 2, color: color2); + static final verticalLine3 = VerticalLine(x: 3, color: color3); + static final verticalLine4 = VerticalLine(x: 4, color: color4); + static final verticalLine5 = VerticalLine(x: 5, color: color5); + static final horizontalRangeAnnotation0 = + HorizontalRangeAnnotation(y1: 0, y2: 1, color: color0); + static final horizontalRangeAnnotation1 = + HorizontalRangeAnnotation(y1: 1, y2: 2, color: color1); + + static final horizontalRangeAnnotation2 = + HorizontalRangeAnnotation(y1: 2, y2: 3, color: color2); + + static final horizontalRangeAnnotation3 = + HorizontalRangeAnnotation(y1: 3, y2: 4, color: color3); + + static final horizontalRangeAnnotation4 = + HorizontalRangeAnnotation(y1: 4, y2: 5, color: color4); + + static final verticalRangeAnnotation0 = + VerticalRangeAnnotation(x1: 0, x2: 1, color: color0); + + static final verticalRangeAnnotation1 = + VerticalRangeAnnotation(x1: 1, x2: 2, color: color1); + + static final verticalRangeAnnotation2 = + VerticalRangeAnnotation(x1: 2, x2: 3, color: color2); + + static final verticalRangeAnnotation3 = + VerticalRangeAnnotation(x1: 3, x2: 4, color: color3); -final radarTouchedSpot5 = RadarTouchedSpot( - radarDataSet1, - 0, - radarDataSet1.dataEntries.first, - 1, - flSpot1, - Offset.zero, -); + static final verticalRangeAnnotation4 = + VerticalRangeAnnotation(x1: 4, x2: 5, color: color4); -final radarTouchedSpot6 = RadarTouchedSpot( - radarDataSet1, - 0, - radarDataSet1.dataEntries.first, - 0, - flSpot2, - Offset.zero, -); + static const RadarEntry radarEntry0 = RadarEntry(value: 0); -final radarTouchedSpot7 = RadarTouchedSpot( - radarDataSet1, - 0, - radarDataSet1.dataEntries.first, - 0, - flSpot1, - const Offset(3, 5), -); + static const RadarEntry radarEntry1 = RadarEntry(value: 1); -final RadarChartData radarChartData1 = RadarChartData( - dataSets: [radarDataSet1], - radarBackgroundColor: Colors.yellow, - radarBorderData: const BorderSide(color: Colors.purple, width: 5), - borderData: borderData1, - gridBorderData: const BorderSide(color: Colors.blue, width: 2), - getTitle: (index, angle) => RadarChartTitle(text: 'testTitle', angle: angle), - titlePositionPercentageOffset: 0.2, - titleTextStyle: const TextStyle(color: Colors.white, fontSize: 12), - radarTouchData: radarTouchData1, - tickCount: 5, - tickBorderData: const BorderSide(width: 4), - ticksTextStyle: const TextStyle(color: Colors.white, fontSize: 12), -); + static const RadarEntry radarEntry2 = RadarEntry(value: 2); + static const RadarEntry radarEntry3 = RadarEntry(value: 3); + static const RadarEntry radarEntry4 = RadarEntry(value: 4); + static final RadarDataSet radarDataSet1 = RadarDataSet( + dataEntries: [radarEntry1, radarEntry2, radarEntry3], + ); + static final RadarDataSet radarDataSet2 = RadarDataSet( + dataEntries: [radarEntry3, radarEntry1, radarEntry2], + ); + static final RadarTouchedSpot radarTouchedSpot = RadarTouchedSpot( + radarDataSet1, + 0, + radarEntry1, + 0, + flSpot1, + offset1, + ); + static final pieChartSection0 = PieChartSectionData( + value: 0, + color: color0, + radius: 0, + ); + static final pieChartSection1 = PieChartSectionData( + value: 1, + color: color1, + radius: 1, + ); -final RadarChartData radarChartData1Clone = radarChartData1.copyWith(); + static final pieChartSection2 = PieChartSectionData( + value: 2, + color: color2, + radius: 2, + ); -final RadarChartData radarChartData2 = RadarChartData( - dataSets: [radarDataSet2], - radarBackgroundColor: Colors.blue, - radarBorderData: const BorderSide(color: Colors.pink, width: 3), - borderData: borderData1, - gridBorderData: const BorderSide(color: Colors.red, width: 3), - getTitle: (index, angle) => RadarChartTitle(text: 'testTitle2', angle: angle), - titlePositionPercentageOffset: 0.5, - titleTextStyle: const TextStyle(color: Colors.black, fontSize: 5), - radarTouchData: radarTouchData2, - tickCount: 1, - tickBorderData: const BorderSide(color: Colors.pink, width: 2), - ticksTextStyle: const TextStyle(color: Colors.purple, fontSize: 10), -); + static final pieChartSection3 = PieChartSectionData( + value: 3, + color: color3, + radius: 3, + ); -const Line line1 = Line(Offset.zero, Offset(10, 10)); -const Line line2 = Line(Offset(-4, -12), Offset(6, 8)); -const Line line3 = Line(Offset(18, -1), Offset.zero); -const Line line4 = Line(Offset(8, 8), Offset(-4, -22)); -const Line line5 = Line(Offset(2, 3), Offset(5, 8)); + static final pieChartSection4 = PieChartSectionData( + value: 4, + color: color4, + radius: 4, + ); -const TextStyle textStyle1 = - TextStyle(color: Colors.red, fontWeight: FontWeight.bold); -const TextStyle textStyle2 = - TextStyle(color: Colors.green, fontWeight: FontWeight.w200); + static final scatterSpot0 = ScatterSpot( + 0, + 0, + dotPainter: FlDotCirclePainter(color: color0), + ); -const TextSpan textSpan1 = TextSpan(text: 'faketext1', style: textStyle1); -const TextSpan textSpan2 = TextSpan(text: 'faketext2', style: textStyle2); + static final scatterSpot1 = ScatterSpot( + 1, + 1, + dotPainter: FlDotCirclePainter(color: color1), + ); -final DefaultTextStyle defaultTextStyle1 = DefaultTextStyle( - style: const TextStyle(), - child: Container(), -); + static final scatterSpot2 = ScatterSpot( + 2, + 2, + dotPainter: FlDotCirclePainter(color: color2), + ); + static final scatterSpot3 = ScatterSpot( + 3, + 3, + dotPainter: FlDotCirclePainter(color: color3), + ); + static final scatterSpot4 = ScatterSpot( + 4, + 4, + dotPainter: FlDotCirclePainter(color: color4), + ); + static final scatterTouchedSpot = ScatterTouchedSpot(scatterSpot1, 0); + static final pieChartSectionData1 = PieChartSectionData(value: 12); -final candlestickTouchData1 = CandlestickTouchData( - enabled: false, -); + static final pieChartSectionData2 = PieChartSectionData(value: 22); -final candlestickSpot1 = CandlestickSpot( - x: 0, - open: 10, - high: 100, - low: 0, - close: 20, -); + static final pieTouchedSection1 = PieTouchedSection( + pieChartSectionData1, + 0, + 12, + 33, + ); -final CandlestickSpot candlestickSpot1Clone = candlestickSpot1.copyWith(); + static final lineBarSpot1 = TouchLineBarSpot( + lineChartBarData1, + 0, + lineChartBarData1.spots.first, + 0, + ); -final candlestickSpot2 = CandlestickSpot( - x: 10, - open: 30, - high: 110, - low: 10, - close: 20, -); + static final lineBarSpot2 = TouchLineBarSpot( + MockData.lineChartBarData1, + 1, + MockData.lineChartBarData1.spots.last, + 2, + ); -final CandlestickSpot candlestickSpot2Clone = candlestickSpot2.copyWith(); + static final lineTouchResponse1 = LineTouchResponse( + touchLocation: Offset.zero, + touchChartCoordinate: Offset.zero, + lineBarSpots: [lineBarSpot1, lineBarSpot2], + ); + static final barChartRodData1 = BarChartRodData(toY: 11); -final candlestickSpot3 = CandlestickSpot( - x: 20, - open: 30, - high: 120, - low: 20, - close: 40, -); + static final barChartRodData2 = BarChartRodData(toY: 22); -final candlestickSpot4 = CandlestickSpot( - x: 30, - open: 40, - high: 130, - low: 30, - close: 50, -); + static final barTouchedSpot = BarTouchedSpot( + BarChartGroupData(x: 0, barRods: [barChartRodData1, barChartRodData2]), + 0, + barChartRodData1, + 0, + null, + -1, + flSpot1, + offset1, + ); + static const gradient1 = LinearGradient( + colors: [ + MockData.color0, + MockData.color1, + ], + ); + static final barGroupData0 = BarChartGroupData( + x: 0, + barRods: [MockData.barChartRodData1, MockData.barChartRodData2], + ); -final candlestickSpot5 = CandlestickSpot( - x: -50, - open: -40, - high: -130, - low: -30, - close: -50, -); + static final barGroupData1 = BarChartGroupData( + x: 1, + barRods: [MockData.barChartRodData1, MockData.barChartRodData2], + ); -final candleStickChartData1 = CandlestickChartData( - candlestickSpots: [ - candlestickSpot1, - candlestickSpot2, - candlestickSpot3, - candlestickSpot4, - ], - candlestickPainter: DefaultCandlestickPainter(), - titlesData: MockData.flTitlesData1, - candlestickTouchData: candlestickTouchData1, - showingTooltipIndicators: [0, 1, 2], - gridData: flGridData1, - borderData: borderData1, - minX: 0, - maxX: 1000, - minY: 0, - maxY: 1000, - baselineX: 0, - baselineY: 0, - backgroundColor: Colors.white, - rangeAnnotations: rangeAnnotations1, - clipData: const FlClipData.none(), -); + static final barGroupData2 = BarChartGroupData( + x: 2, + barRods: [MockData.barChartRodData1, MockData.barChartRodData2], + ); -final CandlestickChartData candleStickChartData1Clone = - candleStickChartData1.copyWith(); + static final barChartData1 = BarChartData( + barGroups: [barGroupData0, barGroupData1, barGroupData2], + ); -final candleStickChartData2 = CandlestickChartData( - candlestickSpots: [ - candlestickSpot1, - candlestickSpot2, - candlestickSpot3, - candlestickSpot4, - ], - candlestickPainter: DefaultCandlestickPainter(), - titlesData: MockData.flTitlesData2, - candlestickTouchData: candlestickTouchData1, - showingTooltipIndicators: [1, 2, 3], - gridData: flGridData1, - borderData: borderData1, - minX: 0, - maxX: 1000, - minY: 0, - maxY: 1000, - baselineX: 0, - baselineY: 0, - backgroundColor: Colors.white, - rangeAnnotations: rangeAnnotations1, - clipData: const FlClipData.all(), - rotationQuarterTurns: 1, -); + static const sideTitles1 = SideTitles( + reservedSize: 10, + interval: 23, + ); -Color candlestickChartGetTooltipRedColor(CandlestickSpot spots) => Colors.red; + static const sideTitles1Clone = SideTitles( + reservedSize: 10, + interval: 23, + ); -Color candlestickChartGetTooltipGreenColor(CandlestickSpot spots) => - Colors.green; + static const sideTitles2 = SideTitles( + reservedSize: 10, + interval: 12, + ); + static const sideTitles3 = SideTitles( + reservedSize: 10, + getTitlesWidget: getTitles, + interval: 12, + ); + static const sideTitles4 = SideTitles( + reservedSize: 11, + showTitles: true, + getTitlesWidget: getTitles, + interval: 12, + ); + static const sideTitles5 = SideTitles( + reservedSize: 10, + getTitlesWidget: getTitles, + interval: 43, + ); + static const sideTitles6 = SideTitles( + reservedSize: 10, + getTitlesWidget: getTitles, + interval: 22, + ); + static const sideTitleFitInsideData1 = SideTitleFitInsideData( + enabled: true, + axisPosition: 0, + parentAxisSize: 100, + distanceFromEdge: 0, + ); + static const sideTitleFitInsideData1Clone = SideTitleFitInsideData( + enabled: true, + axisPosition: 0, + parentAxisSize: 100, + distanceFromEdge: 0, + ); -CandlestickTooltipItem? candlestickChartGetTooltipItems( - FlCandlestickPainter painter, - CandlestickSpot touchedSpot, - int spotIndex, -) { - return CandlestickTooltipItem( - 'check', - textStyle: const TextStyle(color: Colors.blue), - bottomMargin: 23, + static const sideTitleFitInsideData2 = SideTitleFitInsideData( + enabled: true, + axisPosition: 0, + parentAxisSize: 100, + distanceFromEdge: 10, ); -} + static const sideTitleFitInsideData3 = SideTitleFitInsideData( + enabled: false, + axisPosition: 0, + parentAxisSize: 100, + distanceFromEdge: 0, + ); + static const sideTitleFitInsideData4 = SideTitleFitInsideData( + enabled: true, + axisPosition: 200, + parentAxisSize: 200, + distanceFromEdge: 0, + ); + static const sideTitleFitInsideData5 = SideTitleFitInsideData( + enabled: true, + axisPosition: 200, + parentAxisSize: 200, + distanceFromEdge: 10, + ); + static const sideTitleFitInsideData6 = SideTitleFitInsideData( + enabled: false, + axisPosition: 200, + parentAxisSize: 200, + distanceFromEdge: 0, + ); + static const widget1 = Text('axis1'); + static const widget2 = Text('axis2'); -final CandlestickTouchTooltipData candlestickTouchTooltipData1 = - CandlestickTouchTooltipData( - tooltipBorderRadius: const BorderRadius.all(Radius.circular(23)), - tooltipPadding: const EdgeInsets.all(11), - getTooltipColor: candlestickChartGetTooltipGreenColor, - maxContentWidth: 33, - fitInsideVertically: true, - fitInsideHorizontally: false, - getTooltipItems: candlestickChartGetTooltipItems, - tooltipBorder: const BorderSide(color: Colors.red), -); -final CandlestickTouchTooltipData candlestickTouchTooltipData1Clone = - CandlestickTouchTooltipData( - tooltipBorderRadius: const BorderRadius.all(Radius.circular(23)), - tooltipPadding: const EdgeInsets.all(11), - getTooltipColor: candlestickChartGetTooltipGreenColor, - maxContentWidth: 33, - fitInsideVertically: true, - fitInsideHorizontally: false, - getTooltipItems: candlestickChartGetTooltipItems, - tooltipBorder: const BorderSide(color: Colors.red), -); -final CandlestickTouchTooltipData candlestickTouchTooltipData2 = - CandlestickTouchTooltipData( - tooltipBorderRadius: const BorderRadius.all(Radius.circular(23)), - tooltipPadding: const EdgeInsets.all(11), - getTooltipColor: candlestickChartGetTooltipGreenColor, - maxContentWidth: 33, - fitInsideVertically: true, - fitInsideHorizontally: false, - getTooltipItems: candlestickChartGetTooltipItems, - tooltipBorder: const BorderSide(color: Colors.blue), - tooltipHorizontalAlignment: FLHorizontalAlignment.left, -); -final CandlestickTouchTooltipData candlestickTouchTooltipData3 = - CandlestickTouchTooltipData( - tooltipBorderRadius: const BorderRadius.all(Radius.circular(23)), - tooltipPadding: const EdgeInsets.all(11), - getTooltipColor: candlestickChartGetTooltipGreenColor, - maxContentWidth: 33, - fitInsideVertically: true, - fitInsideHorizontally: false, - getTooltipItems: candlestickChartGetTooltipItems, - tooltipBorder: const BorderSide(color: Colors.red, width: 2), - tooltipHorizontalAlignment: FLHorizontalAlignment.right, - tooltipHorizontalOffset: 10, -); + static const widget3 = Text('axis3'); + static const widget4 = Text('axis4'); + static const widget5 = Text('axis5'); + static const axisTitles1 = AxisTitles( + axisNameWidget: widget1, + sideTitles: sideTitles1, + ); + static const axisTitles1Clone = AxisTitles( + axisNameWidget: widget1, + sideTitles: sideTitles1Clone, + ); -final candlestickTouchedSpot1 = CandlestickTouchedSpot(candlestickSpot1, 0); + static const axisTitles2 = AxisTitles( + axisNameWidget: widget2, + sideTitles: sideTitles2, + ); + static const axisTitles3 = AxisTitles( + axisNameWidget: widget3, + sideTitles: sideTitles3, + ); + static const axisTitles4 = AxisTitles( + axisNameWidget: widget4, + sideTitles: sideTitles4, + ); + static const axisTitles5 = AxisTitles( + axisNameWidget: widget5, + axisNameSize: 889, + sideTitles: sideTitles4, + ); + static const flTitlesData1 = FlTitlesData( + bottomTitles: axisTitles1, + topTitles: axisTitles2, + rightTitles: axisTitles3, + leftTitles: axisTitles4, + ); + static const flTitlesData1Clone = FlTitlesData( + bottomTitles: axisTitles1Clone, + topTitles: axisTitles2, + rightTitles: axisTitles3, + leftTitles: axisTitles4, + ); + + static const flTitlesData2 = FlTitlesData( + topTitles: axisTitles2, + rightTitles: axisTitles3, + leftTitles: axisTitles4, + ); + static const flTitlesData3 = FlTitlesData( + bottomTitles: axisTitles1, + rightTitles: axisTitles3, + leftTitles: axisTitles4, + ); + static const flTitlesData4 = FlTitlesData( + bottomTitles: axisTitles1, + topTitles: axisTitles2, + leftTitles: axisTitles4, + ); + static const flTitlesData5 = FlTitlesData( + bottomTitles: axisTitles1, + topTitles: axisTitles2, + rightTitles: axisTitles3, + ); + static const flTitlesData6 = FlTitlesData( + show: false, + bottomTitles: axisTitles1, + topTitles: axisTitles2, + rightTitles: axisTitles3, + leftTitles: axisTitles4, + ); + static Image image1() { + if (_image1 != null) { + return _image1!; + } + _image1 = Image.asset('asdf/asdf'); + return _image1!; + } + + static Picture picture1() { + if (_picture1 != null) { + return _picture1!; + } + final recorder1 = PictureRecorder(); + Canvas(recorder1).drawLine(offset1, offset2, paint1); + _picture1 = recorder1.endRecording(); + return _picture1!; + } +} diff --git a/test/chart/gauge_chart/gauge_chart_data_test.dart b/test/chart/gauge_chart/gauge_chart_data_test.dart new file mode 100644 index 000000000..e751f4655 --- /dev/null +++ b/test/chart/gauge_chart/gauge_chart_data_test.dart @@ -0,0 +1,824 @@ +import 'package:fl_chart/fl_chart.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import '../data_pool.dart'; + +void main() { + group('GaugeChart Data equality check', () { + test('GaugeChartData equality test', () { + expect(gaugeChartData1 == gaugeChartData1Clone, true); + + expect( + gaugeChartData1 == + gaugeChartData1Clone.copyWith( + rings: const [ + GaugeProgressRing(value: 0.5, color: Colors.black), + ], + ), + false, + ); + + expect( + gaugeChartData1 == + gaugeChartData1Clone.copyWith( + borderData: FlBorderData( + show: true, + border: Border.all(color: Colors.green), + ), + ), + false, + ); + + expect( + gaugeChartData1 == + gaugeChartData1Clone.copyWith( + rings: [gaugeRing1.copyWith(strokeCap: StrokeCap.square)], + ), + false, + ); + + expect( + gaugeChartData1 == + gaugeChartData1Clone.copyWith(touchData: gaugeTouchData2), + false, + ); + + expect( + gaugeChartData1 == gaugeChartData1Clone.copyWith(startDegreeOffset: 0), + false, + ); + + expect( + gaugeChartData1 == gaugeChartData1Clone.copyWith(sweepAngle: 10), + false, + ); + + expect( + gaugeChartData1 == + gaugeChartData1Clone.copyWith( + direction: GaugeDirection.counterClockwise, + ), + false, + ); + + expect( + gaugeChartData1 == gaugeChartData1Clone.copyWith(defaultRingWidth: 7), + false, + ); + + expect( + gaugeChartData1 == gaugeChartData1Clone.copyWith(ringsSpace: 2), + false, + ); + }); + + test('GaugeChartData asserts', () { + expect( + () => GaugeChartData( + maxValue: 0, + rings: const [GaugeProgressRing(value: 0, color: Colors.red)], + ), + throwsAssertionError, + ); + + expect( + () => GaugeChartData( + sweepAngle: 0, + rings: const [ + GaugeProgressRing(value: 0.5, color: Colors.red), + ], + ), + throwsAssertionError, + ); + + expect( + () => GaugeChartData( + sweepAngle: 400, + rings: const [ + GaugeProgressRing(value: 0.5, color: Colors.red), + ], + ), + throwsAssertionError, + ); + + // progress value outside [minValue, maxValue] + expect( + () => GaugeChartData( + rings: const [GaugeProgressRing(value: 2, color: Colors.red)], + ), + throwsAssertionError, + ); + + // zone outside [minValue, maxValue] + expect( + () => GaugeChartData( + rings: const [ + GaugeZonesRing( + zones: [GaugeZone(from: 0, to: 2, color: Colors.red)], + ), + ], + ), + throwsAssertionError, + ); + + // empty zones in a chart rejected at GaugeChartData level + expect( + () => GaugeChartData( + rings: const [GaugeZonesRing(zones: [])], + ), + throwsAssertionError, + ); + + // negative ringsSpace + expect( + () => GaugeChartData( + rings: const [ + GaugeProgressRing(value: 0.5, color: Colors.red), + ], + ringsSpace: -1, + ), + throwsAssertionError, + ); + + // invalid ring width + expect( + () => GaugeProgressRing(value: 0.5, color: Colors.red, width: 0), + throwsAssertionError, + ); + + // invalid zone range + expect( + () => GaugeZone(from: 0.5, to: 0.3, color: Colors.red), + throwsAssertionError, + ); + + // negative zonesSpace + expect( + () => GaugeZonesRing( + zones: const [GaugeZone(from: 0, to: 1, color: Colors.red)], + zonesSpace: -1, + ), + throwsAssertionError, + ); + }); + + test('GaugeChartData.progress factory', () { + final data = GaugeChartData.progress( + value: 0.6, + color: Colors.red, + width: 20, + backgroundColor: Colors.grey, + ); + expect(data.rings.length, 1); + final ring = data.rings.first as GaugeProgressRing; + expect(ring.value, 0.6); + expect(ring.color, Colors.red); + expect(ring.width, 20); + expect(ring.backgroundColor, Colors.grey); + expect(data.defaultRingWidth, 20); + + final clampedHigh = GaugeChartData.progress( + value: 2, + color: Colors.red, + width: 20, + ); + expect( + (clampedHigh.rings.first as GaugeProgressRing).value, + 1, + ); + + final clampedLow = GaugeChartData.progress( + value: -1, + color: Colors.red, + width: 20, + ); + expect((clampedLow.rings.first as GaugeProgressRing).value, 0); + }); + + test('GaugeProgressRing equality and copyWith', () { + expect(gaugeRing1 == gaugeRing1.copyWith(), true); + expect(gaugeRing1 == gaugeRing1.copyWith(value: 0.4), false); + expect(gaugeRing1 == gaugeRing1.copyWith(color: Colors.red), false); + expect(gaugeRing1 == gaugeRing1.copyWith(width: 10), false); + expect( + gaugeRing1 == gaugeRing1.copyWith(backgroundColor: Colors.pink), + false, + ); + }); + + test('GaugeProgressRing.lerp', () { + const a = GaugeProgressRing( + value: 0.2, + color: Colors.red, + width: 10, + backgroundColor: Colors.pink, + ); + const b = GaugeProgressRing( + value: 0.8, + color: Colors.blue, + width: 30, + backgroundColor: Colors.lightBlue, + ); + final mid = GaugeProgressRing.lerp(a, b, 0.5); + expect(mid.value, closeTo(0.5, 1e-9)); + expect(mid.width, 20); + expect(mid.color, Color.lerp(Colors.red, Colors.blue, 0.5)); + expect( + mid.backgroundColor, + Color.lerp(Colors.pink, Colors.lightBlue, 0.5), + ); + }); + + test('GaugeZone equality and lerp', () { + const a = GaugeZone(from: 0.1, to: 0.5, color: Colors.red); + const b = GaugeZone(from: 0.3, to: 0.9, color: Colors.blue); + expect(a == a.copyWith(), true); + expect(a == a.copyWith(from: 0.2), false); + expect(a == a.copyWith(to: 0.4), false); + expect(a == a.copyWith(color: Colors.green), false); + + final mid = GaugeZone.lerp(a, b, 0.5); + expect(mid.from, closeTo(0.2, 1e-9)); + expect(mid.to, closeTo(0.7, 1e-9)); + expect(mid.color, Color.lerp(Colors.red, Colors.blue, 0.5)); + }); + + test('GaugeZonesRing equality, copyWith, lerp', () { + const a = GaugeZonesRing( + zones: [ + GaugeZone(from: 0, to: 0.5, color: Colors.red), + GaugeZone(from: 0.5, to: 1, color: Colors.green), + ], + zonesSpace: 4, + width: 10, + ); + const a2 = GaugeZonesRing( + zones: [ + GaugeZone(from: 0, to: 0.5, color: Colors.red), + GaugeZone(from: 0.5, to: 1, color: Colors.green), + ], + zonesSpace: 4, + width: 10, + ); + expect(a == a2, true); + expect(a == a.copyWith(width: 20), false); + expect(a == a.copyWith(zonesSpace: 8), false); + + const b = GaugeZonesRing( + zones: [ + GaugeZone(from: 0, to: 0.3, color: Colors.red), + GaugeZone(from: 0.3, to: 1, color: Colors.blue), + ], + zonesSpace: 8, + width: 20, + ); + final mid = GaugeZonesRing.lerp(a, b, 0.5); + expect(mid.width, 15); + expect(mid.zonesSpace, closeTo(6, 1e-9)); + expect(mid.zones[0].to, closeTo(0.4, 1e-9)); + expect( + mid.zones[1].color, + Color.lerp(Colors.green, Colors.blue, 0.5), + ); + }); + + test('GaugeRing.lerp dispatches by type', () { + const progressA = GaugeProgressRing(value: 0.2, color: Colors.red); + const progressB = GaugeProgressRing(value: 0.8, color: Colors.red); + final progressMid = + GaugeRing.lerp(progressA, progressB, 0.5) as GaugeProgressRing; + expect(progressMid.value, closeTo(0.5, 1e-9)); + + const zonesA = GaugeZonesRing( + zones: [GaugeZone(from: 0, to: 0.5, color: Colors.red)], + width: 10, + ); + const zonesB = GaugeZonesRing( + zones: [GaugeZone(from: 0, to: 0.5, color: Colors.red)], + width: 20, + ); + final zonesMid = GaugeRing.lerp(zonesA, zonesB, 0.5) as GaugeZonesRing; + expect(zonesMid.width, 15); + + // Cross-type snaps to target + expect(GaugeRing.lerp(progressA, zonesA, 0.2), zonesA); + expect(GaugeRing.lerp(zonesA, progressA, 0.8), progressA); + }); + + test('GaugeZonesRing.copyWith with zones parameter', () { + const a = GaugeZonesRing( + zones: [GaugeZone(from: 0, to: 0.5, color: Colors.red)], + width: 10, + ); + final b = a.copyWith( + zones: const [GaugeZone(from: 0.1, to: 0.9, color: Colors.green)], + ); + expect(b.zones.length, 1); + expect(b.zones.first.from, 0.1); + expect(b.width, 10); + }); + + test('GaugeTouchData equality test', () { + expect(gaugeTouchData1 == gaugeTouchData1Clone, true); + expect(gaugeTouchData1 == gaugeTouchData2, false); + + expect( + gaugeTouchData1 == + GaugeTouchData(enabled: true, touchCallback: (_, __) {}), + false, + ); + + expect( + gaugeTouchData1 == + GaugeTouchData( + enabled: true, + mouseCursorResolver: (_, __) => MouseCursor.uncontrolled, + ), + false, + ); + + expect( + gaugeTouchData1 == + GaugeTouchData(enabled: true, longPressDuration: Duration.zero), + false, + ); + }); + + test('GaugeTouchedRing equality test', () { + expect(gaugeTouchedRing1 == gaugeTouchedRingClone1, true); + expect(gaugeTouchedRing1 == gaugeTouchedRing2, false); + expect(gaugeTouchedRing1 == gaugeTouchedRing3, false); + }); + + test('GaugeTicks equality, copyWith-free, lerp', () { + const a = GaugeTicks( + count: 5, + offset: 4, + labelStyle: TextStyle(fontSize: 10), + labelOffset: 3, + ); + const aClone = GaugeTicks( + count: 5, + offset: 4, + labelStyle: TextStyle(fontSize: 10), + labelOffset: 3, + ); + const b = GaugeTicks( + count: 9, + offset: 8, + position: GaugeTickPosition.inner, + painter: GaugeTickLinePainter(length: 12), + checkToShowTick: GaugeTicks.hideEndpoints, + labelStyle: TextStyle(fontSize: 14), + labelOffset: 7, + ); + expect(a == aClone, true); + expect(a == b, false); + expect( + a == + const GaugeTicks( + count: 5, + checkToShowTick: GaugeTicks.hideEndpoints, + ), + false, + ); + + // Null handling — lerp returns the non-null side (b). + expect(GaugeTicks.lerp(null, null, 0.5), isNull); + expect(GaugeTicks.lerp(null, a, 0.5), a); + expect(GaugeTicks.lerp(a, null, 0.5), isNull); + + final mid = GaugeTicks.lerp(a, b, 0.5)!; + expect(mid.count, 7); + expect(mid.offset, 6); + expect(mid.labelOffset, 5); + expect(mid.position, GaugeTickPosition.inner); // snaps to b + // CheckToShowGaugeTick snaps to b too. + expect(identical(mid.checkToShowTick, GaugeTicks.hideEndpoints), true); + final midPainter = mid.painter as GaugeTickLinePainter; + expect(midPainter.length, 9); + }); + + test('GaugeTicks.hideEndpoints and showAll predicates', () { + const info0 = GaugeTickInfo( + index: 0, + count: 5, + value: 0, + minValue: 0, + maxValue: 100, + ); + const infoMid = GaugeTickInfo( + index: 2, + count: 5, + value: 50, + minValue: 0, + maxValue: 100, + ); + const infoLast = GaugeTickInfo( + index: 4, + count: 5, + value: 100, + minValue: 0, + maxValue: 100, + ); + + expect(GaugeTicks.showAll(info0), true); + expect(GaugeTicks.showAll(infoMid), true); + expect(GaugeTicks.showAll(infoLast), true); + + expect(GaugeTicks.hideEndpoints(info0), false); + expect(GaugeTicks.hideEndpoints(infoMid), true); + expect(GaugeTicks.hideEndpoints(infoLast), false); + }); + + test('GaugeTickLinePainter equality, getSize, lerp, draw', () { + const a = GaugeTickLinePainter(); + const b = GaugeTickLinePainter(); + const c = GaugeTickLinePainter(length: 10); + expect(a == b, true); + expect(a == c, false); + expect(a.getSize(), const Size(6, 2)); + + // Cross-type lerp snaps to b. + final fallback = a.lerp(const GaugeTickCirclePainter(), 0.3); + expect(fallback, isA()); + + // Same-type lerp blends lengths. + final mid = a.lerp(c, 0.5) as GaugeTickLinePainter; + expect(mid.length, 8); + + // draw calls canvas.drawLine(zero, (length, 0), paint). + final canvas = _RecordingCanvas(); + a.draw( + canvas, + const GaugeTickInfo( + index: 0, + count: 1, + value: 1, + minValue: 1, + maxValue: 2, + ), + ); + expect(canvas.lines.length, 1); + expect(canvas.lines.first.p1, Offset.zero); + expect(canvas.lines.first.p2, const Offset(6, 0)); + }); + + test('GaugeTickCirclePainter equality, getSize, lerp, draw', () { + const a = GaugeTickCirclePainter(color: Colors.red); + const b = GaugeTickCirclePainter(color: Colors.red); + const c = GaugeTickCirclePainter(radius: 5, color: Colors.red); + expect(a == b, true); + expect(a == c, false); + expect(a.getSize(), const Size.fromRadius(3)); + + // strokeWidth > 0 draws two circles (stroke + fill). + const withStroke = GaugeTickCirclePainter( + radius: 4, + color: Colors.red, + strokeWidth: 2, + strokeColor: Colors.blue, + ); + final canvas = _RecordingCanvas(); + withStroke.draw( + canvas, + const GaugeTickInfo( + index: 0, + count: 1, + value: 1, + minValue: 1, + maxValue: 2, + ), + ); + expect(canvas.circles.length, 2); + expect(canvas.circles[0].paint.style, PaintingStyle.stroke); + expect(canvas.circles[1].paint.style, PaintingStyle.fill); + + // strokeWidth == 0 draws only fill. + final canvas2 = _RecordingCanvas(); + const GaugeTickCirclePainter(radius: 4, color: Colors.red).draw( + canvas2, + const GaugeTickInfo( + index: 0, + count: 1, + value: 1, + minValue: 1, + maxValue: 2, + ), + ); + expect(canvas2.circles.length, 1); + expect(canvas2.circles.first.paint.style, PaintingStyle.fill); + }); + + test('GaugePointer equality, copyWith, lerp', () { + const a = GaugePointer( + value: 0.2, + painter: GaugePointerNeedlePainter(length: 40), + ); + const b = GaugePointer( + value: 0.8, + painter: GaugePointerNeedlePainter(length: 80), + ); + expect(a == a.copyWith(), true); + expect(a == a.copyWith(value: 0.5), false); + expect( + a == a.copyWith(painter: const GaugePointerNeedlePainter(length: 99)), + false, + ); + + final mid = GaugePointer.lerp(a, b, 0.5); + expect(mid.value, closeTo(0.5, 1e-9)); + expect( + (mid.painter as GaugePointerNeedlePainter).length, + closeTo(60, 1e-9), + ); + }); + + test('GaugePointerNeedlePainter equality, getSize, lerp, draw', () { + const a = GaugePointerNeedlePainter(length: 40, width: 6); + const b = GaugePointerNeedlePainter(length: 40, width: 6); + const c = GaugePointerNeedlePainter(length: 80, width: 6); + expect(a == b, true); + expect(a == c, false); + expect(a.getSize(), const Size(40, 6)); + + // Cross-type lerp snaps to b. + final fallback = a.lerp(const GaugePointerCirclePainter(), 0.2); + expect(fallback, isA()); + + // Same-type lerp blends. + final mid = a.lerp(c, 0.5) as GaugePointerNeedlePainter; + expect(mid.length, 60); + + // Draw emits a single filled triangle path. + final canvas = _RecordingCanvas(); + a.draw(canvas); + expect(canvas.paths.length, 1); + expect(canvas.paths.first.paint.style, PaintingStyle.fill); + }); + + test('GaugePointerCirclePainter draws at anchorRadius on +x axis', () { + // Non-const construction so assertion lines get runtime coverage. + const a = GaugePointerCirclePainter( + radius: 5, + anchorRadius: 100, + color: Colors.red, + ); + final canvas = _RecordingCanvas(); + a.draw(canvas); + // anchorRadius on +x: circle centered at (100, 0). + expect(canvas.circles.length, 1); + expect(canvas.circles.first.center, const Offset(100, 0)); + expect(canvas.circles.first.radius, 5); + + // With strokeWidth > 0, outline first then fill. + const outlined = GaugePointerCirclePainter( + radius: 5, + strokeWidth: 2, + strokeColor: Colors.blue, + ); + final canvas2 = _RecordingCanvas(); + outlined.draw(canvas2); + expect(canvas2.circles.length, 2); + expect(canvas2.circles[0].paint.style, PaintingStyle.stroke); + expect(canvas2.circles[1].paint.style, PaintingStyle.fill); + + // Asserts fire on invalid inputs. + expect( + () => GaugePointerCirclePainter(radius: 0), + throwsAssertionError, + ); + expect( + () => GaugePointerCirclePainter(anchorRadius: -1), + throwsAssertionError, + ); + expect( + () => GaugePointerCirclePainter(strokeWidth: -1), + throwsAssertionError, + ); + }); + + test('GaugePointerCirclePainter equality, getSize, lerp', () { + const a = GaugePointerCirclePainter(radius: 5, anchorRadius: 100); + const b = GaugePointerCirclePainter(radius: 5, anchorRadius: 100); + const c = GaugePointerCirclePainter(radius: 9, anchorRadius: 100); + expect(a == b, true); + expect(a == c, false); + + // getSize: width = anchorRadius + radius + strokeWidth; height = 2 * that. + expect(a.getSize(), const Size(105, 10)); + const withStroke = GaugePointerCirclePainter(radius: 5, strokeWidth: 2); + expect(withStroke.getSize(), const Size(7, 14)); + + // Same-type lerp blends fields. + final mid = a.lerp(c, 0.5) as GaugePointerCirclePainter; + expect(mid.radius, 7); + expect(mid.anchorRadius, 100); + + // Cross-type lerp snaps to b. + final fallback = a.lerp(const GaugePointerNeedlePainter(), 0.3); + expect(fallback, isA()); + }); + + test('GaugeTickCirclePainter lerp (same-type + cross-type)', () { + const a = GaugeTickCirclePainter(); + const c = GaugeTickCirclePainter(radius: 9); + final mid = a.lerp(c, 0.5) as GaugeTickCirclePainter; + expect(mid.radius, 6); + + // Cross-type lerp to a line painter snaps to b. + final fallback = a.lerp(const GaugeTickLinePainter(), 0.5); + expect(fallback, isA()); + + // Non-const construction exercises the assertion branch. + expect(() => GaugeTickCirclePainter(radius: 0), throwsAssertionError); + }); + + test('CheckToShowGaugeTickInfo equality and props', () { + const a = GaugeTickInfo( + index: 1, + count: 5, + value: 25, + minValue: 0, + maxValue: 100, + ); + const b = GaugeTickInfo( + index: 1, + count: 5, + value: 25, + minValue: 0, + maxValue: 100, + ); + const c = GaugeTickInfo( + index: 2, + count: 5, + value: 50, + minValue: 0, + maxValue: 100, + ); + expect(a == b, true); + expect(a == c, false); + expect(a.props.length, 5); + }); + + test('GaugeChartData.pointers default, copyWith, lerp', () { + final empty = GaugeChartData( + rings: const [GaugeProgressRing(value: 0.5, color: Colors.red)], + ); + expect(empty.pointers, isEmpty); + + final withPointers = empty.copyWith(pointers: const [gaugePointer1]); + expect(withPointers.pointers, hasLength(1)); + expect(withPointers.pointers.first.value, 0.6); + + // Lerp two charts with different pointer lists. + final a = empty.copyWith( + pointers: const [ + GaugePointer(value: 0.2), + ], + ); + final b = empty.copyWith( + pointers: const [ + GaugePointer(value: 0.8), + ], + ); + final mid = a.lerp(a, b, 0.5); + expect(mid.pointers.single.value, closeTo(0.5, 1e-9)); + }); + + test('GaugeChartDataTween lerp', () { + final a = GaugeChartData( + rings: const [ + GaugeProgressRing( + value: 0.2, + color: MockData.color0, + width: 5, + strokeCap: StrokeCap.round, + ), + ], + startDegreeOffset: 0, + touchData: GaugeTouchData( + touchCallback: (_, __) {}, + longPressDuration: const Duration(seconds: 7), + mouseCursorResolver: (_, __) => MouseCursor.defer, + ), + ); + + final b = GaugeChartData( + rings: const [ + GaugeProgressRing( + value: 0.8, + color: MockData.color2, + width: 3, + strokeCap: StrokeCap.square, + ), + ], + startDegreeOffset: 20, + sweepAngle: 230, + touchData: GaugeTouchData( + touchCallback: (_, __) {}, + longPressDuration: const Duration(seconds: 7), + mouseCursorResolver: (_, __) => MouseCursor.defer, + ), + ); + + final data = GaugeChartDataTween(begin: a, end: b).lerp(0.5); + + expect(data.rings.length, 1); + final lerped = data.rings.first as GaugeProgressRing; + expect(lerped.value, closeTo(0.5, 1e-9)); + expect(lerped.width, 4); + expect(data.startDegreeOffset, 10); + expect(data.sweepAngle, 250); + expect(lerped.strokeCap, StrokeCap.square); + expect(data.gaugeTouchData, b.gaugeTouchData); + }); + + test('GaugeChartData.lerp throws on illegal state', () { + final gauge = GaugeChartData( + rings: const [ + GaugeProgressRing(value: 0.5, color: MockData.color0), + ], + sweepAngle: 180, + ); + + expect( + () => gauge.lerp(_DummyData(), _DummyData(), 0.3), + throwsA(isA()), + ); + }); + + test('GaugeTouchResponse.copyWith', () { + final response = GaugeTouchResponse( + touchLocation: const Offset(10, 20), + touchedRing: gaugeTouchedRing1, + ); + + final same = response.copyWith(); + expect(same.touchLocation, response.touchLocation); + expect(same.touchedRing, response.touchedRing); + + final updated = response.copyWith( + touchLocation: const Offset(30, 40), + touchedRing: gaugeTouchedRing2, + ); + expect(updated.touchLocation, const Offset(30, 40)); + expect(updated.touchedRing, gaugeTouchedRing2); + }); + }); +} + +class _DummyData extends BaseChartData { + _DummyData(); + + @override + BaseChartData lerp(BaseChartData a, BaseChartData b, double t) => this; +} + +class _RecordedCircle { + const _RecordedCircle(this.center, this.radius, this.paint); + + final Offset center; + final double radius; + final Paint paint; +} + +class _RecordedLine { + const _RecordedLine(this.p1, this.p2, this.paint); + + final Offset p1; + final Offset p2; + final Paint paint; +} + +class _RecordedPath { + const _RecordedPath(this.path, this.paint); + + final Path path; + final Paint paint; +} + +class _RecordingCanvas implements Canvas { + final List<_RecordedCircle> circles = <_RecordedCircle>[]; + final List<_RecordedLine> lines = <_RecordedLine>[]; + final List<_RecordedPath> paths = <_RecordedPath>[]; + + @override + void drawCircle(Offset c, double radius, Paint paint) { + circles.add(_RecordedCircle(c, radius, paint)); + } + + @override + void drawLine(Offset p1, Offset p2, Paint paint) { + lines.add(_RecordedLine(p1, p2, paint)); + } + + @override + void drawPath(Path path, Paint paint) { + paths.add(_RecordedPath(path, paint)); + } + + @override + dynamic noSuchMethod(Invocation invocation) => null; +} diff --git a/test/chart/gauge_chart/gauge_chart_painter_test.dart b/test/chart/gauge_chart/gauge_chart_painter_test.dart new file mode 100644 index 000000000..fe008b85e --- /dev/null +++ b/test/chart/gauge_chart/gauge_chart_painter_test.dart @@ -0,0 +1,1183 @@ +import 'dart:math'; + +import 'package:fl_chart/fl_chart.dart'; +import 'package:fl_chart/src/chart/base/base_chart/base_chart_painter.dart'; +import 'package:fl_chart/src/chart/gauge_chart/gauge_chart_painter.dart'; +import 'package:fl_chart/src/utils/canvas_wrapper.dart'; +import 'package:fl_chart/src/utils/utils.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; + +import '../data_pool.dart'; +import 'gauge_chart_painter_test.mocks.dart'; + +@GenerateMocks([Canvas, CanvasWrapper, BuildContext, Utils]) +void main() { + final utilsMainInstance = Utils(); + + /// Installs a mocked [Utils] whose [radians] / [degrees] methods pass + /// values through unchanged. This lets tests assert on the *degree* + /// arguments passed to [Canvas.drawArc] instead of radian values. + MockUtils installIdentityUtilsMock() { + final mockUtils = MockUtils(); + Utils.changeInstance(mockUtils); + when(mockUtils.radians(any)).thenAnswer( + (inv) => inv.positionalArguments[0] as double, + ); + when(mockUtils.degrees(any)).thenAnswer( + (inv) => inv.positionalArguments[0] as double, + ); + when(mockUtils.getThemeAwareTextStyle(any, any)).thenAnswer( + (inv) => (inv.positionalArguments[1] as TextStyle?) ?? const TextStyle(), + ); + return mockUtils; + } + + /// Installs a mocked [Utils] that delegates radians/degrees to the real + /// implementation — used by handleTouch tests that need honest + /// conversions. + MockUtils installRealUtilsMock() { + final mockUtils = MockUtils(); + Utils.changeInstance(mockUtils); + when(mockUtils.radians(any)).thenAnswer( + (inv) => utilsMainInstance.radians(inv.positionalArguments[0] as double), + ); + when(mockUtils.degrees(any)).thenAnswer( + (inv) => utilsMainInstance.degrees(inv.positionalArguments[0] as double), + ); + return mockUtils; + } + + group('paint()', () { + test('dispatches to drawSections (no ticks)', () { + const viewSize = Size(400, 400); + final data = GaugeChartData( + rings: const [ + GaugeProgressRing(value: 0.5, color: Colors.red, width: 2), + ], + sweepAngle: 90, + ); + final gaugePainter = GaugeChartPainter(); + final holder = + PaintHolder(data, data, TextScaler.noScaling); + installIdentityUtilsMock(); + + final mockCanvasWrapper = MockCanvasWrapper(); + when(mockCanvasWrapper.size).thenAnswer((_) => viewSize); + when(mockCanvasWrapper.canvas).thenReturn(MockCanvas()); + gaugePainter.paint(MockBuildContext(), mockCanvasWrapper, holder); + + // One drawArc for the ring's filled portion (no background). + verify(mockCanvasWrapper.drawArc(any, any, any, any, any)).called(1); + Utils.changeInstance(utilsMainInstance); + }); + }); + + group('drawSections()', () { + test('single ring draws only filled arc when backgroundColor is null', () { + const viewSize = Size(400, 400); + final data = GaugeChartData( + rings: const [ + GaugeProgressRing(value: 0.5, color: MockData.color0, width: 2), + ], + startDegreeOffset: 0, + sweepAngle: 90, + ); + final gaugePainter = GaugeChartPainter(); + final holder = + PaintHolder(data, data, TextScaler.noScaling); + installIdentityUtilsMock(); + + final mockCanvasWrapper = MockCanvasWrapper(); + when(mockCanvasWrapper.size).thenAnswer((_) => viewSize); + when(mockCanvasWrapper.canvas).thenReturn(MockCanvas()); + + final captured = >[]; + when( + mockCanvasWrapper.drawArc( + captureAny, + captureAny, + captureAny, + captureAny, + captureAny, + ), + ).thenAnswer((inv) { + captured.add({ + 'rect': inv.positionalArguments[0] as Rect, + 'start_angle': inv.positionalArguments[1] as double, + 'sweep_angle': inv.positionalArguments[2] as double, + 'paint_color': (inv.positionalArguments[4] as Paint).color, + 'paint_stroke_width': + (inv.positionalArguments[4] as Paint).strokeWidth, + }); + }); + + gaugePainter.drawSections(mockCanvasWrapper, holder); + + expect(captured.length, 1); + expect(captured[0]['start_angle'], 0); + // 0.5/1.0 * 90° = 45° + expect(captured[0]['sweep_angle'], 45); + expect(captured[0]['paint_color'], isSameColorAs(MockData.color0)); + expect(captured[0]['paint_stroke_width'], 2); + Utils.changeInstance(utilsMainInstance); + }); + + test('draws background arc + filled arc when backgroundColor is set', () { + const viewSize = Size(400, 400); + final data = GaugeChartData( + rings: const [ + GaugeProgressRing( + value: 0.5, + color: MockData.color0, + width: 8, + backgroundColor: MockData.color1, + ), + ], + startDegreeOffset: 10, + sweepAngle: 90, + ); + final gaugePainter = GaugeChartPainter(); + final holder = + PaintHolder(data, data, TextScaler.noScaling); + installIdentityUtilsMock(); + + final mockCanvasWrapper = MockCanvasWrapper(); + when(mockCanvasWrapper.size).thenAnswer((_) => viewSize); + when(mockCanvasWrapper.canvas).thenReturn(MockCanvas()); + + final captured = >[]; + when( + mockCanvasWrapper.drawArc( + captureAny, + captureAny, + captureAny, + captureAny, + captureAny, + ), + ).thenAnswer((inv) { + captured.add({ + 'start_angle': inv.positionalArguments[1] as double, + 'sweep_angle': inv.positionalArguments[2] as double, + 'paint_color': (inv.positionalArguments[4] as Paint).color, + 'paint_stroke_width': + (inv.positionalArguments[4] as Paint).strokeWidth, + }); + }); + + gaugePainter.drawSections(mockCanvasWrapper, holder); + + expect(captured.length, 2); + // Background: full sweep + expect(captured[0]['start_angle'], 10); + expect(captured[0]['sweep_angle'], 90); + expect(captured[0]['paint_color'], isSameColorAs(MockData.color1)); + // Filled: value/range * sweep + expect(captured[1]['start_angle'], 10); + expect(captured[1]['sweep_angle'], 45); + expect(captured[1]['paint_color'], isSameColorAs(MockData.color0)); + Utils.changeInstance(utilsMainInstance); + }); + + test('multiple rings stack innermost-first with ringsSpace', () { + const viewSize = Size(400, 400); + final data = GaugeChartData( + rings: const [ + // innermost + GaugeProgressRing(value: 0.5, color: Colors.red, width: 10), + GaugeProgressRing(value: 0.8, color: Colors.green, width: 20), + // outermost + GaugeProgressRing(value: 0.3, color: Colors.blue, width: 15), + ], + sweepAngle: 180, + ringsSpace: 4, + ); + final gaugePainter = GaugeChartPainter(); + final holder = + PaintHolder(data, data, TextScaler.noScaling); + installIdentityUtilsMock(); + + final mockCanvasWrapper = MockCanvasWrapper(); + when(mockCanvasWrapper.size).thenAnswer((_) => viewSize); + when(mockCanvasWrapper.canvas).thenReturn(MockCanvas()); + + final rects = []; + when( + mockCanvasWrapper.drawArc(captureAny, any, any, any, any), + ).thenAnswer((inv) { + rects.add(inv.positionalArguments[0] as Rect); + }); + + gaugePainter.drawSections(mockCanvasWrapper, holder); + + // 3 rings, no backgroundColor → 3 draws. + expect(rects.length, 3); + + // Outer = 200. Widths 10, 20, 15; gaps 4 each; total depth = 53. + // innermost edge = 200 - 53 = 147. + // Section 0 (innermost, width 10): stroke center = 147 + 5 = 152. + // Section 1 (width 20, space 4): 161 + 10 = 171. + // Section 2 (outermost, width 15): 185 + 7.5 = 192.5. + expect(rects[0].shortestSide / 2, 152); + expect(rects[1].shortestSide / 2, 171); + expect(rects[2].shortestSide / 2, 192.5); + Utils.changeInstance(utilsMainInstance); + }); + + test('non-default min/max scales the filled sweep proportionally', () { + const viewSize = Size(400, 400); + final data = GaugeChartData( + maxValue: 100, + rings: const [ + GaugeProgressRing(value: 75, color: Colors.red, width: 10), + ], + sweepAngle: 180, + ); + final gaugePainter = GaugeChartPainter(); + final holder = + PaintHolder(data, data, TextScaler.noScaling); + installIdentityUtilsMock(); + + final mockCanvasWrapper = MockCanvasWrapper(); + when(mockCanvasWrapper.size).thenAnswer((_) => viewSize); + when(mockCanvasWrapper.canvas).thenReturn(MockCanvas()); + + final sweeps = []; + when( + mockCanvasWrapper.drawArc(any, any, captureAny, any, any), + ).thenAnswer((inv) { + sweeps.add(inv.positionalArguments[2] as double); + }); + + gaugePainter.drawSections(mockCanvasWrapper, holder); + expect(sweeps.length, 1); + // 75/100 * 180 = 135 + expect(sweeps[0], 135); + Utils.changeInstance(utilsMainInstance); + }); + + test('counterClockwise direction flips the filled sweep sign', () { + const viewSize = Size(400, 400); + final data = GaugeChartData( + rings: const [ + GaugeProgressRing(value: 0.5, color: Colors.red, width: 5), + ], + sweepAngle: 100, + direction: GaugeDirection.counterClockwise, + ); + final gaugePainter = GaugeChartPainter(); + final holder = + PaintHolder(data, data, TextScaler.noScaling); + installIdentityUtilsMock(); + + final mockCanvasWrapper = MockCanvasWrapper(); + when(mockCanvasWrapper.size).thenAnswer((_) => viewSize); + when(mockCanvasWrapper.canvas).thenReturn(MockCanvas()); + + final sweeps = []; + when( + mockCanvasWrapper.drawArc(any, any, captureAny, any, any), + ).thenAnswer((inv) { + sweeps.add(inv.positionalArguments[2] as double); + }); + + gaugePainter.drawSections(mockCanvasWrapper, holder); + // -100 * 0.5/1.0 = -50 + expect(sweeps[0], -50); + Utils.changeInstance(utilsMainInstance); + }); + }); + + group('handleTouch()', () { + test('returns null for touches outside the arc angular range', () { + const viewSize = Size(250, 250); + final data = GaugeChartData( + rings: const [ + GaugeProgressRing(value: 1, color: Colors.red, width: 30), + ], + startDegreeOffset: 0, + sweepAngle: 90, // arc from 0° to 90° + ); + final gaugePainter = GaugeChartPainter(); + final holder = + PaintHolder(data, data, TextScaler.noScaling); + installRealUtilsMock(); + + // Touch above center (angle = -90°), outside [0°, 90°]. + final result = gaugePainter.handleTouch( + const Offset(125, 30), + viewSize, + holder, + ); + expect(result, isNull); + Utils.changeInstance(utilsMainInstance); + }); + + test('reports correct ring and isOnValue for a touch on the filled part', + () { + const viewSize = Size(400, 400); + final data = GaugeChartData( + maxValue: 100, + rings: const [ + GaugeProgressRing(value: 70, color: Colors.red, width: 20), + ], + startDegreeOffset: 0, + sweepAngle: 180, + ); + final gaugePainter = GaugeChartPainter(); + final holder = + PaintHolder(data, data, TextScaler.noScaling); + installRealUtilsMock(); + + // Ring stroke center at 200 - 10 = 190. + // Touch the ring at 45° (value 25 — on the filled portion since 25 < 70). + const center = Offset(200, 200); + const deg = 45.0; + const rad = deg * pi / 180; + final touch = center + Offset(cos(rad), sin(rad)) * 190; + final hit = gaugePainter.handleTouch(touch, viewSize, holder); + + expect(hit, isNotNull); + expect(hit!.touchedRingIndex, 0); + expect(hit.touchValue, closeTo(25, 1e-6)); + expect(hit.isOnValue, isTrue); + Utils.changeInstance(utilsMainInstance); + }); + + test( + 'ring hit on background part returns isOnValue=false with a ' + 'valid touchValue', () { + const viewSize = Size(400, 400); + final data = GaugeChartData( + maxValue: 100, + rings: const [ + GaugeProgressRing(value: 70, color: Colors.red, width: 20), + ], + startDegreeOffset: 0, + sweepAngle: 180, + ); + final gaugePainter = GaugeChartPainter(); + final holder = + PaintHolder(data, data, TextScaler.noScaling); + installRealUtilsMock(); + + // Touch at 162° (value 90 — past 70, on the background portion). + const center = Offset(200, 200); + const deg = 162.0; + const rad = deg * pi / 180; + final touch = center + Offset(cos(rad), sin(rad)) * 190; + final hit = gaugePainter.handleTouch(touch, viewSize, holder); + + expect(hit, isNotNull); + expect(hit!.touchedRingIndex, 0); + expect(hit.touchValue, closeTo(90, 1e-6)); + expect(hit.isOnValue, isFalse); + Utils.changeInstance(utilsMainInstance); + }); + + test('inner rings are reachable when stacked with ringsSpace', () { + const viewSize = Size(400, 400); + final data = GaugeChartData( + rings: const [ + GaugeProgressRing(value: 1, color: Colors.red, width: 10), + GaugeProgressRing(value: 1, color: Colors.blue, width: 10), + ], + ringsSpace: 4, + startDegreeOffset: 0, + sweepAngle: 180, + ); + final gaugePainter = GaugeChartPainter(); + final holder = + PaintHolder(data, data, TextScaler.noScaling); + installRealUtilsMock(); + + // Sections listed innermost-first: total depth = 10 + 4 + 10 = 24, + // innermost edge at 200 - 24 = 176. Ring 0 (innermost) stroke center + // 181; ring 1 (outermost) stroke center 195. + const center = Offset(200, 200); + final hitInner = gaugePainter.handleTouch( + center + const Offset(181, 0), + viewSize, + holder, + ); + expect(hitInner!.touchedRingIndex, 0); + + final hitOuter = gaugePainter.handleTouch( + center + const Offset(195, 0), + viewSize, + holder, + ); + expect(hitOuter!.touchedRingIndex, 1); + + // Touch far inside the gauge (radius 50) — on-arc angularly but + // outside every ring's radial band, even after the threshold + // extension. + final miss = gaugePainter.handleTouch( + center + const Offset(50, 0), + viewSize, + holder, + ); + expect(miss, isNotNull); + expect(miss!.touchedRing, isNull); + expect(miss.touchedRingIndex, -1); + expect(miss.isOnValue, isFalse); + Utils.changeInstance(utilsMainInstance); + }); + }); + + group('drawSections() — zones ring', () { + test('draws one arc per zone with correct sweep and color', () { + const viewSize = Size(400, 400); + final data = GaugeChartData( + maxValue: 100, + rings: const [ + GaugeZonesRing( + width: 10, + zones: [ + GaugeZone(from: 0, to: 50, color: MockData.color0), + GaugeZone(from: 50, to: 80, color: MockData.color1), + GaugeZone(from: 80, to: 100, color: MockData.color2), + ], + ), + ], + startDegreeOffset: 0, + sweepAngle: 180, + ); + final gaugePainter = GaugeChartPainter(); + final holder = + PaintHolder(data, data, TextScaler.noScaling); + installIdentityUtilsMock(); + + final mockCanvasWrapper = MockCanvasWrapper(); + when(mockCanvasWrapper.size).thenAnswer((_) => viewSize); + when(mockCanvasWrapper.canvas).thenReturn(MockCanvas()); + + final captured = >[]; + when( + mockCanvasWrapper.drawArc( + captureAny, + captureAny, + captureAny, + captureAny, + captureAny, + ), + ).thenAnswer((inv) { + captured.add({ + 'start': inv.positionalArguments[1] as double, + 'sweep': inv.positionalArguments[2] as double, + 'color': (inv.positionalArguments[4] as Paint).color, + }); + }); + + gaugePainter.drawSections(mockCanvasWrapper, holder); + + expect(captured.length, 3); + // Zone 0: 0..50 → 90° + expect(captured[0]['start'], 0); + expect(captured[0]['sweep'], 90); + expect(captured[0]['color'], isSameColorAs(MockData.color0)); + // Zone 1: 50..80 → starts at 90°, sweeps 54° + expect(captured[1]['start'], 90); + expect(captured[1]['sweep'], closeTo(54, 1e-9)); + // Zone 2: 80..100 → starts at 144°, sweeps 36° + expect(captured[2]['start'], closeTo(144, 1e-9)); + expect(captured[2]['sweep'], closeTo(36, 1e-9)); + Utils.changeInstance(utilsMainInstance); + }); + + test( + 'zonesSpace draws zones full-angular and clears internal-boundary ' + 'strips via saveLayer + BlendMode.clear', () { + const viewSize = Size(400, 400); + final data = GaugeChartData( + maxValue: 100, + rings: const [ + GaugeZonesRing( + width: 10, + zonesSpace: 8, + zones: [ + GaugeZone(from: 0, to: 50, color: MockData.color0), + GaugeZone(from: 50, to: 80, color: MockData.color1), + GaugeZone(from: 80, to: 100, color: MockData.color2), + ], + ), + ], + startDegreeOffset: 0, + sweepAngle: 180, + ); + final gaugePainter = GaugeChartPainter(); + final holder = + PaintHolder(data, data, TextScaler.noScaling); + installIdentityUtilsMock(); + + final mockCanvasWrapper = MockCanvasWrapper(); + when(mockCanvasWrapper.size).thenAnswer((_) => viewSize); + when(mockCanvasWrapper.canvas).thenReturn(MockCanvas()); + + final arcs = >[]; + when( + mockCanvasWrapper.drawArc( + captureAny, + captureAny, + captureAny, + captureAny, + captureAny, + ), + ).thenAnswer((inv) { + arcs.add({ + 'start': inv.positionalArguments[1] as double, + 'sweep': inv.positionalArguments[2] as double, + 'color': (inv.positionalArguments[4] as Paint).color, + }); + }); + final clearPaths = []; + when(mockCanvasWrapper.drawPath(captureAny, captureAny)) + .thenAnswer((inv) { + clearPaths.add(inv.positionalArguments[1] as Paint); + }); + + gaugePainter.drawSections(mockCanvasWrapper, holder); + + // saveLayer/restore wrap the zones-ring paint. + verify(mockCanvasWrapper.saveLayer(any, any)).called(1); + verify(mockCanvasWrapper.restore()).called(1); + + // Every zone is drawn at its raw full angular range — no shrink. + expect(arcs.length, 3); + expect(arcs[0]['start'], 0); + expect(arcs[0]['sweep'], closeTo(90, 1e-9)); + expect(arcs[1]['start'], closeTo(90, 1e-9)); + expect(arcs[1]['sweep'], closeTo(54, 1e-9)); + expect(arcs[2]['start'], closeTo(144, 1e-9)); + expect(arcs[2]['sweep'], closeTo(36, 1e-9)); + + // One clear strip per internal boundary (zones.length - 1). + expect(clearPaths.length, 2); + for (final paint in clearPaths) { + expect(paint.blendMode, BlendMode.clear); + expect(paint.style, PaintingStyle.fill); + } + Utils.changeInstance(utilsMainInstance); + }); + + test( + 'zonesSpace with StrokeCap.round zones re-adds cap circles on ' + 'each side of the carved gap', () { + const viewSize = Size(400, 400); + final data = GaugeChartData( + maxValue: 100, + rings: const [ + GaugeZonesRing( + width: 10, + zonesSpace: 16, + zones: [ + GaugeZone( + from: 0, + to: 50, + color: MockData.color0, + strokeCap: StrokeCap.round, + ), + GaugeZone( + from: 50, + to: 100, + color: MockData.color1, + strokeCap: StrokeCap.round, + ), + ], + ), + ], + startDegreeOffset: 0, + sweepAngle: 180, + ); + final gaugePainter = GaugeChartPainter(); + final holder = + PaintHolder(data, data, TextScaler.noScaling); + installIdentityUtilsMock(); + + final mockCanvasWrapper = MockCanvasWrapper(); + when(mockCanvasWrapper.size).thenAnswer((_) => viewSize); + when(mockCanvasWrapper.canvas).thenReturn(MockCanvas()); + + final caps = []; + when(mockCanvasWrapper.drawCircle(captureAny, captureAny, captureAny)) + .thenAnswer((inv) { + caps.add((inv.positionalArguments[2] as Paint).color); + }); + + gaugePainter.drawSections(mockCanvasWrapper, holder); + + // At the single internal boundary, a cap is re-drawn on each side — + // one in zone 0's color, one in zone 1's color. + expect(caps.length, 2); + expect(caps[0], isSameColorAs(MockData.color0)); + expect(caps[1], isSameColorAs(MockData.color1)); + Utils.changeInstance(utilsMainInstance); + }); + + test( + 'zonesSpace with mixed StrokeCap — only round zones get cap ' + 're-added', () { + const viewSize = Size(400, 400); + final data = GaugeChartData( + maxValue: 100, + rings: const [ + GaugeZonesRing( + width: 10, + zonesSpace: 16, + zones: [ + GaugeZone( + from: 0, + to: 50, + color: MockData.color0, + strokeCap: StrokeCap.round, + ), + GaugeZone(from: 50, to: 100, color: MockData.color1), + ], + ), + ], + startDegreeOffset: 0, + sweepAngle: 180, + ); + final gaugePainter = GaugeChartPainter(); + final holder = + PaintHolder(data, data, TextScaler.noScaling); + installIdentityUtilsMock(); + + final mockCanvasWrapper = MockCanvasWrapper(); + when(mockCanvasWrapper.size).thenAnswer((_) => viewSize); + when(mockCanvasWrapper.canvas).thenReturn(MockCanvas()); + + final caps = []; + when(mockCanvasWrapper.drawCircle(captureAny, captureAny, captureAny)) + .thenAnswer((inv) { + caps.add((inv.positionalArguments[2] as Paint).color); + }); + + gaugePainter.drawSections(mockCanvasWrapper, holder); + + // Only zone 0 (round) gets a cap re-added; zone 1 (butt) does not. + expect(caps, [isSameColorAs(MockData.color0)]); + Utils.changeInstance(utilsMainInstance); + }); + + test('zonesSpace == 0 skips saveLayer and draws zones directly', () { + const viewSize = Size(400, 400); + final data = GaugeChartData( + maxValue: 100, + rings: const [ + GaugeZonesRing( + width: 10, + zones: [ + GaugeZone(from: 0, to: 50, color: MockData.color0), + GaugeZone(from: 50, to: 100, color: MockData.color1), + ], + ), + ], + startDegreeOffset: 0, + sweepAngle: 180, + ); + final gaugePainter = GaugeChartPainter(); + final holder = + PaintHolder(data, data, TextScaler.noScaling); + installIdentityUtilsMock(); + + final mockCanvasWrapper = MockCanvasWrapper(); + when(mockCanvasWrapper.size).thenAnswer((_) => viewSize); + when(mockCanvasWrapper.canvas).thenReturn(MockCanvas()); + + gaugePainter.drawSections(mockCanvasWrapper, holder); + + verifyNever(mockCanvasWrapper.saveLayer(any, any)); + verifyNever(mockCanvasWrapper.restore()); + verifyNever(mockCanvasWrapper.drawPath(any, any)); + verify(mockCanvasWrapper.drawArc(any, any, any, any, any)).called(2); + Utils.changeInstance(utilsMainInstance); + }); + }); + + group('handleTouch() — zones ring', () { + test('returns the hit zone for a touch inside a zone', () { + const viewSize = Size(400, 400); + final data = GaugeChartData( + maxValue: 100, + rings: const [ + GaugeZonesRing( + width: 20, + zones: [ + GaugeZone(from: 0, to: 50, color: Colors.red), + GaugeZone(from: 50, to: 80, color: Colors.amber), + GaugeZone(from: 80, to: 100, color: Colors.green), + ], + ), + ], + startDegreeOffset: 0, + sweepAngle: 180, + ); + final gaugePainter = GaugeChartPainter(); + final holder = + PaintHolder(data, data, TextScaler.noScaling); + installRealUtilsMock(); + + // ring stroke center = 200 - 10 = 190 + const center = Offset(200, 200); + // Touch at 45° — value = 25 → zone 0 + { + const rad = 45 * pi / 180; + final touch = center + Offset(cos(rad), sin(rad)) * 190; + final hit = gaugePainter.handleTouch(touch, viewSize, holder); + expect(hit, isNotNull); + expect(hit!.touchedRingIndex, 0); + expect(hit.touchedZoneIndex, 0); + expect(hit.touchedZone?.color, Colors.red); + expect(hit.isOnValue, isFalse); // zones never flag isOnValue + } + // Touch at 135° — value = 75 → zone 1 + { + const rad = 135 * pi / 180; + final touch = center + Offset(cos(rad), sin(rad)) * 190; + final hit = gaugePainter.handleTouch(touch, viewSize, holder); + expect(hit!.touchedZoneIndex, 1); + expect(hit.touchedZone?.color, Colors.amber); + } + Utils.changeInstance(utilsMainInstance); + }); + + test('reports null zone when touch falls in a gap between zones', () { + const viewSize = Size(400, 400); + final data = GaugeChartData( + maxValue: 100, + rings: const [ + GaugeZonesRing( + width: 20, + zones: [ + GaugeZone(from: 0, to: 30, color: Colors.red), + // gap 30..70 + GaugeZone(from: 70, to: 100, color: Colors.green), + ], + ), + ], + startDegreeOffset: 0, + sweepAngle: 180, + ); + final gaugePainter = GaugeChartPainter(); + final holder = + PaintHolder(data, data, TextScaler.noScaling); + installRealUtilsMock(); + + // Touch at 90° — value = 50, sits in the gap + const center = Offset(200, 200); + const rad = 90 * pi / 180; + final touch = center + Offset(cos(rad), sin(rad)) * 190; + final hit = gaugePainter.handleTouch(touch, viewSize, holder); + + expect(hit, isNotNull); + // Ring itself IS hit + expect(hit!.touchedRingIndex, 0); + expect(hit.touchedRing, isA()); + // But no zone contains value 50 + expect(hit.touchedZone, isNull); + expect(hit.touchedZoneIndex, -1); + Utils.changeInstance(utilsMainInstance); + }); + }); + + group('drawTicks()', () { + test('no-op when ticks is null', () { + const viewSize = Size(400, 400); + final data = GaugeChartData( + rings: const [ + GaugeProgressRing(value: 1, color: Colors.red, width: 10), + ], + sweepAngle: 90, + ); + final gaugePainter = GaugeChartPainter(); + final holder = + PaintHolder(data, data, TextScaler.noScaling); + installIdentityUtilsMock(); + + final mockCanvasWrapper = MockCanvasWrapper(); + when(mockCanvasWrapper.size).thenAnswer((_) => viewSize); + when(mockCanvasWrapper.canvas).thenReturn(MockCanvas()); + + gaugePainter.drawTicks(MockBuildContext(), mockCanvasWrapper, holder); + + verifyNever(mockCanvasWrapper.save()); + verifyNever(mockCanvasWrapper.translate(any, any)); + verifyNever(mockCanvasWrapper.rotate(any)); + verifyNever(mockCanvasWrapper.drawText(any, any)); + Utils.changeInstance(utilsMainInstance); + }); + + test('draws one save+translate+rotate+restore per tick and calls painter', + () { + const viewSize = Size(400, 400); + final data = GaugeChartData( + rings: const [ + GaugeProgressRing(value: 1, color: Colors.red, width: 10), + ], + startDegreeOffset: 0, + sweepAngle: 90, + ticks: const GaugeTicks( + count: 5, + ), + ); + final gaugePainter = GaugeChartPainter(); + final holder = + PaintHolder(data, data, TextScaler.noScaling); + installIdentityUtilsMock(); + + final mockCanvasWrapper = MockCanvasWrapper(); + when(mockCanvasWrapper.size).thenAnswer((_) => viewSize); + when(mockCanvasWrapper.canvas).thenReturn(MockCanvas()); + + final rotations = []; + when(mockCanvasWrapper.rotate(captureAny)).thenAnswer((inv) { + rotations.add(inv.positionalArguments[0] as double); + }); + + gaugePainter.drawTicks(MockBuildContext(), mockCanvasWrapper, holder); + + // Save / restore wraps every tick's transform. + verify(mockCanvasWrapper.save()).called(5); + verify(mockCanvasWrapper.restore()).called(5); + verify(mockCanvasWrapper.translate(any, any)).called(5); + // Evenly spaced rotations from 0° to 90° (identity mock → degrees). + expect(rotations.length, 5); + expect(rotations[0], 0); + expect(rotations[1], closeTo(22.5, 1e-9)); + expect(rotations[2], closeTo(45, 1e-9)); + expect(rotations[3], closeTo(67.5, 1e-9)); + expect(rotations[4], closeTo(90, 1e-9)); + // No labels configured → no drawText. + verifyNever(mockCanvasWrapper.drawText(any, any)); + Utils.changeInstance(utilsMainInstance); + }); + + test( + 'center position places ticks radially between inner and outer ' + 'ring edges', () { + const viewSize = Size(400, 400); + final data = GaugeChartData( + rings: const [ + GaugeProgressRing(value: 1, color: Colors.red, width: 20), + ], + startDegreeOffset: 0, + sweepAngle: 90, + ticks: const GaugeTicks( + count: 2, + position: GaugeTickPosition.center, + ), + ); + final gaugePainter = GaugeChartPainter(); + final holder = + PaintHolder(data, data, TextScaler.noScaling); + installIdentityUtilsMock(); + + final mockCanvasWrapper = MockCanvasWrapper(); + when(mockCanvasWrapper.size).thenAnswer((_) => viewSize); + when(mockCanvasWrapper.canvas).thenReturn(MockCanvas()); + + gaugePainter.drawTicks(MockBuildContext(), mockCanvasWrapper, holder); + + // Center position uses (outer + inner) / 2 + offset — just asserting + // the branch is exercised (paths hit, no crash). + verify(mockCanvasWrapper.save()).called(2); + verify(mockCanvasWrapper.restore()).called(2); + Utils.changeInstance(utilsMainInstance); + }); + + test('inner position adds π to rotation so +x points toward center', () { + const viewSize = Size(400, 400); + final data = GaugeChartData( + rings: const [ + GaugeProgressRing(value: 1, color: Colors.red, width: 10), + ], + startDegreeOffset: 0, + sweepAngle: 90, + ticks: const GaugeTicks( + count: 2, + position: GaugeTickPosition.inner, + ), + ); + final gaugePainter = GaugeChartPainter(); + final holder = + PaintHolder(data, data, TextScaler.noScaling); + installIdentityUtilsMock(); + + final mockCanvasWrapper = MockCanvasWrapper(); + when(mockCanvasWrapper.size).thenAnswer((_) => viewSize); + when(mockCanvasWrapper.canvas).thenReturn(MockCanvas()); + + final rotations = []; + when(mockCanvasWrapper.rotate(captureAny)).thenAnswer((inv) { + rotations.add(inv.positionalArguments[0] as double); + }); + + gaugePainter.drawTicks(MockBuildContext(), mockCanvasWrapper, holder); + + // Identity mock means `rotate` received a radian-value-identical-to- + // the-degree; we just want to see the +π offset. + expect(rotations.length, 2); + expect(rotations[0], closeTo(pi, 1e-9)); + expect(rotations[1], closeTo(90 + pi, 1e-9)); + Utils.changeInstance(utilsMainInstance); + }); + + test('labelBuilder + labelStyle paints text at each tick', () { + const viewSize = Size(400, 400); + final data = GaugeChartData( + rings: const [ + GaugeProgressRing(value: 1, color: Colors.red, width: 10), + ], + startDegreeOffset: 0, + sweepAngle: 90, + maxValue: 100, + ticks: GaugeTicks( + painter: const GaugeTickLinePainter(length: 4, thickness: 1), + labelBuilder: (v) => v.toStringAsFixed(0), + labelStyle: const TextStyle(fontSize: 10), + ), + ); + final gaugePainter = GaugeChartPainter(); + final holder = + PaintHolder(data, data, TextScaler.noScaling); + installIdentityUtilsMock(); + + final mockCanvasWrapper = MockCanvasWrapper(); + when(mockCanvasWrapper.size).thenAnswer((_) => viewSize); + when(mockCanvasWrapper.canvas).thenReturn(MockCanvas()); + + final labels = []; + when(mockCanvasWrapper.drawText(captureAny, captureAny)) + .thenAnswer((inv) { + final tp = inv.positionalArguments[0] as TextPainter; + labels.add((tp.text! as TextSpan).text!); + }); + + gaugePainter.drawTicks(MockBuildContext(), mockCanvasWrapper, holder); + + // 3 ticks across minValue=0, maxValue=100 → "0", "50", "100". + expect(labels, ['0', '50', '100']); + Utils.changeInstance(utilsMainInstance); + }); + + test('GaugeTicks.hideEndpoints skips first and last ticks + labels', () { + const viewSize = Size(400, 400); + final data = GaugeChartData( + maxValue: 100, + rings: const [ + GaugeProgressRing(value: 1, color: Colors.red, width: 10), + ], + startDegreeOffset: 0, + sweepAngle: 90, + ticks: GaugeTicks( + count: 5, + checkToShowTick: GaugeTicks.hideEndpoints, + labelBuilder: (v) => v.toStringAsFixed(0), + labelStyle: const TextStyle(fontSize: 10), + ), + ); + final gaugePainter = GaugeChartPainter(); + final holder = + PaintHolder(data, data, TextScaler.noScaling); + installIdentityUtilsMock(); + + final mockCanvasWrapper = MockCanvasWrapper(); + when(mockCanvasWrapper.size).thenAnswer((_) => viewSize); + when(mockCanvasWrapper.canvas).thenReturn(MockCanvas()); + + final labels = []; + when(mockCanvasWrapper.drawText(captureAny, captureAny)) + .thenAnswer((inv) { + final tp = inv.positionalArguments[0] as TextPainter; + labels.add((tp.text! as TextSpan).text!); + }); + + gaugePainter.drawTicks(MockBuildContext(), mockCanvasWrapper, holder); + + // 5 ticks total; endpoints (0 and 100) skipped, 3 interior draw. + verify(mockCanvasWrapper.save()).called(3); + verify(mockCanvasWrapper.restore()).called(3); + expect(labels, ['25', '50', '75']); + Utils.changeInstance(utilsMainInstance); + }); + + test( + 'CheckToShowGaugeTick receives index, count, value, min/max and can ' + 'hide arbitrary ticks', () { + const viewSize = Size(400, 400); + final captured = []; + final data = GaugeChartData( + maxValue: 100, + rings: const [ + GaugeProgressRing(value: 1, color: Colors.red, width: 10), + ], + startDegreeOffset: 0, + sweepAngle: 90, + ticks: GaugeTicks( + checkToShowTick: (info) { + captured.add(info); + // Hide only the middle tick. + return info.index != 1; + }, + labelBuilder: (v) => v.toStringAsFixed(0), + labelStyle: const TextStyle(fontSize: 10), + ), + ); + final gaugePainter = GaugeChartPainter(); + final holder = + PaintHolder(data, data, TextScaler.noScaling); + installIdentityUtilsMock(); + + final mockCanvasWrapper = MockCanvasWrapper(); + when(mockCanvasWrapper.size).thenAnswer((_) => viewSize); + when(mockCanvasWrapper.canvas).thenReturn(MockCanvas()); + + final labels = []; + when(mockCanvasWrapper.drawText(captureAny, captureAny)) + .thenAnswer((inv) { + final tp = inv.positionalArguments[0] as TextPainter; + labels.add((tp.text! as TextSpan).text!); + }); + + gaugePainter.drawTicks(MockBuildContext(), mockCanvasWrapper, holder); + + // Callback invoked once per tick, carrying full info. + expect(captured.length, 3); + expect(captured[0].index, 0); + expect(captured[0].value, 0); + expect(captured[0].minValue, 0); + expect(captured[0].maxValue, 100); + expect(captured[0].count, 3); + expect(captured[1].index, 1); + expect(captured[1].value, 50); + expect(captured[2].index, 2); + expect(captured[2].value, 100); + + // Middle hidden, endpoints shown. + expect(labels, ['0', '100']); + Utils.changeInstance(utilsMainInstance); + }); + }); + + group('drawPointers()', () { + test('no-op when pointers list is empty', () { + const viewSize = Size(400, 400); + final data = GaugeChartData( + rings: const [ + GaugeProgressRing(value: 1, color: Colors.red, width: 10), + ], + sweepAngle: 90, + ); + final gaugePainter = GaugeChartPainter(); + final holder = + PaintHolder(data, data, TextScaler.noScaling); + installIdentityUtilsMock(); + + final mockCanvasWrapper = MockCanvasWrapper(); + when(mockCanvasWrapper.size).thenAnswer((_) => viewSize); + when(mockCanvasWrapper.canvas).thenReturn(MockCanvas()); + + gaugePainter.drawPointers(mockCanvasWrapper, holder); + + verifyNever(mockCanvasWrapper.save()); + verifyNever(mockCanvasWrapper.translate(any, any)); + verifyNever(mockCanvasWrapper.rotate(any)); + Utils.changeInstance(utilsMainInstance); + }); + + test( + 'one save/translate/rotate/restore per pointer, angle = ' + 'startDegreeOffset + dir * sweepAngle * progress', () { + const viewSize = Size(400, 400); + final data = GaugeChartData( + maxValue: 100, + rings: const [ + GaugeProgressRing(value: 1, color: Colors.red, width: 10), + ], + startDegreeOffset: 0, + sweepAngle: 180, + pointers: const [ + GaugePointer(value: 0), + GaugePointer(value: 50), + GaugePointer(value: 100), + ], + ); + final gaugePainter = GaugeChartPainter(); + final holder = + PaintHolder(data, data, TextScaler.noScaling); + installIdentityUtilsMock(); + + final mockCanvasWrapper = MockCanvasWrapper(); + when(mockCanvasWrapper.size).thenAnswer((_) => viewSize); + when(mockCanvasWrapper.canvas).thenReturn(MockCanvas()); + + final translations = []; + when(mockCanvasWrapper.translate(captureAny, captureAny)) + .thenAnswer((inv) { + translations.add( + Offset( + inv.positionalArguments[0] as double, + inv.positionalArguments[1] as double, + ), + ); + }); + final rotations = []; + when(mockCanvasWrapper.rotate(captureAny)).thenAnswer((inv) { + rotations.add(inv.positionalArguments[0] as double); + }); + + gaugePainter.drawPointers(mockCanvasWrapper, holder); + + verify(mockCanvasWrapper.save()).called(3); + verify(mockCanvasWrapper.restore()).called(3); + + // Every translate goes to the gauge center (viewSize / 2). + expect(translations, everyElement(const Offset(200, 200))); + + // Angles match: value 0 → 0°, value 50 → 90°, value 100 → 180° + // (identity mock passes the degree through unchanged). + expect(rotations[0], 0); + expect(rotations[1], closeTo(90, 1e-9)); + expect(rotations[2], closeTo(180, 1e-9)); + Utils.changeInstance(utilsMainInstance); + }); + + test('counter-clockwise direction flips the angle sign', () { + const viewSize = Size(400, 400); + final data = GaugeChartData( + maxValue: 100, + rings: const [ + GaugeProgressRing(value: 1, color: Colors.red, width: 10), + ], + startDegreeOffset: 0, + sweepAngle: 180, + direction: GaugeDirection.counterClockwise, + pointers: const [ + GaugePointer(value: 50), + ], + ); + final gaugePainter = GaugeChartPainter(); + final holder = + PaintHolder(data, data, TextScaler.noScaling); + installIdentityUtilsMock(); + + final mockCanvasWrapper = MockCanvasWrapper(); + when(mockCanvasWrapper.size).thenAnswer((_) => viewSize); + when(mockCanvasWrapper.canvas).thenReturn(MockCanvas()); + + final rotations = []; + when(mockCanvasWrapper.rotate(captureAny)).thenAnswer((inv) { + rotations.add(inv.positionalArguments[0] as double); + }); + + gaugePainter.drawPointers(mockCanvasWrapper, holder); + + // dir = -1, progress 0.5, so angle = 0 + -1 * 180 * 0.5 = -90. + expect(rotations.single, closeTo(-90, 1e-9)); + Utils.changeInstance(utilsMainInstance); + }); + }); +} diff --git a/test/chart/gauge_chart/gauge_chart_painter_test.mocks.dart b/test/chart/gauge_chart/gauge_chart_painter_test.mocks.dart new file mode 100644 index 000000000..5f2ee2d72 --- /dev/null +++ b/test/chart/gauge_chart/gauge_chart_painter_test.mocks.dart @@ -0,0 +1,1505 @@ +// Mocks generated by Mockito 5.4.6 from annotations +// in fl_chart/test/chart/gauge_chart/gauge_chart_painter_test.dart. +// Do not manually edit this file. + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:typed_data' as _i5; +import 'dart:ui' as _i2; + +import 'package:fl_chart/fl_chart.dart' as _i7; +import 'package:fl_chart/src/utils/canvas_wrapper.dart' as _i6; +import 'package:fl_chart/src/utils/utils.dart' as _i8; +import 'package:flutter/cupertino.dart' as _i3; +import 'package:flutter/foundation.dart' as _i4; +import 'package:mockito/mockito.dart' as _i1; +import 'package:mockito/src/dummies.dart' as _i9; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: must_be_immutable +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class +// ignore_for_file: invalid_use_of_internal_member + +class _FakeRect_0 extends _i1.SmartFake implements _i2.Rect { + _FakeRect_0( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeCanvas_1 extends _i1.SmartFake implements _i2.Canvas { + _FakeCanvas_1( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeSize_2 extends _i1.SmartFake implements _i2.Size { + _FakeSize_2( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeWidget_3 extends _i1.SmartFake implements _i3.Widget { + _FakeWidget_3( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); + + @override + String toString({_i3.DiagnosticLevel? minLevel = _i3.DiagnosticLevel.info}) => + super.toString(); +} + +class _FakeInheritedWidget_4 extends _i1.SmartFake + implements _i3.InheritedWidget { + _FakeInheritedWidget_4( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); + + @override + String toString({_i3.DiagnosticLevel? minLevel = _i3.DiagnosticLevel.info}) => + super.toString(); +} + +class _FakeDiagnosticsNode_5 extends _i1.SmartFake + implements _i3.DiagnosticsNode { + _FakeDiagnosticsNode_5( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); + + @override + String toString({ + _i4.TextTreeConfiguration? parentConfiguration, + _i3.DiagnosticLevel? minLevel = _i3.DiagnosticLevel.info, + }) => + super.toString(); +} + +class _FakeOffset_6 extends _i1.SmartFake implements _i2.Offset { + _FakeOffset_6( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeBorderSide_7 extends _i1.SmartFake implements _i3.BorderSide { + _FakeBorderSide_7( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); + + @override + String toString({_i3.DiagnosticLevel? minLevel = _i3.DiagnosticLevel.info}) => + super.toString(); +} + +class _FakeTextStyle_8 extends _i1.SmartFake implements _i3.TextStyle { + _FakeTextStyle_8( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); + + @override + String toString({_i3.DiagnosticLevel? minLevel = _i3.DiagnosticLevel.info}) => + super.toString(); +} + +/// A class which mocks [Canvas]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockCanvas extends _i1.Mock implements _i2.Canvas { + MockCanvas() { + _i1.throwOnMissingStub(this); + } + + @override + void save() => super.noSuchMethod( + Invocation.method( + #save, + [], + ), + returnValueForMissingStub: null, + ); + + @override + void saveLayer( + _i2.Rect? bounds, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #saveLayer, + [ + bounds, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void restore() => super.noSuchMethod( + Invocation.method( + #restore, + [], + ), + returnValueForMissingStub: null, + ); + + @override + void restoreToCount(int? count) => super.noSuchMethod( + Invocation.method( + #restoreToCount, + [count], + ), + returnValueForMissingStub: null, + ); + + @override + int getSaveCount() => (super.noSuchMethod( + Invocation.method( + #getSaveCount, + [], + ), + returnValue: 0, + ) as int); + + @override + void translate( + double? dx, + double? dy, + ) => + super.noSuchMethod( + Invocation.method( + #translate, + [ + dx, + dy, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void scale( + double? sx, [ + double? sy, + ]) => + super.noSuchMethod( + Invocation.method( + #scale, + [ + sx, + sy, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void rotate(double? radians) => super.noSuchMethod( + Invocation.method( + #rotate, + [radians], + ), + returnValueForMissingStub: null, + ); + + @override + void skew( + double? sx, + double? sy, + ) => + super.noSuchMethod( + Invocation.method( + #skew, + [ + sx, + sy, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void transform(_i5.Float64List? matrix4) => super.noSuchMethod( + Invocation.method( + #transform, + [matrix4], + ), + returnValueForMissingStub: null, + ); + + @override + _i5.Float64List getTransform() => (super.noSuchMethod( + Invocation.method( + #getTransform, + [], + ), + returnValue: _i5.Float64List(0), + ) as _i5.Float64List); + + @override + void clipRect( + _i2.Rect? rect, { + _i2.ClipOp? clipOp = _i2.ClipOp.intersect, + bool? doAntiAlias = true, + }) => + super.noSuchMethod( + Invocation.method( + #clipRect, + [rect], + { + #clipOp: clipOp, + #doAntiAlias: doAntiAlias, + }, + ), + returnValueForMissingStub: null, + ); + + @override + void clipRRect( + _i2.RRect? rrect, { + bool? doAntiAlias = true, + }) => + super.noSuchMethod( + Invocation.method( + #clipRRect, + [rrect], + {#doAntiAlias: doAntiAlias}, + ), + returnValueForMissingStub: null, + ); + + @override + void clipRSuperellipse( + _i2.RSuperellipse? rsuperellipse, { + bool? doAntiAlias = true, + }) => + super.noSuchMethod( + Invocation.method( + #clipRSuperellipse, + [rsuperellipse], + {#doAntiAlias: doAntiAlias}, + ), + returnValueForMissingStub: null, + ); + + @override + void clipPath( + _i2.Path? path, { + bool? doAntiAlias = true, + }) => + super.noSuchMethod( + Invocation.method( + #clipPath, + [path], + {#doAntiAlias: doAntiAlias}, + ), + returnValueForMissingStub: null, + ); + + @override + _i2.Rect getLocalClipBounds() => (super.noSuchMethod( + Invocation.method( + #getLocalClipBounds, + [], + ), + returnValue: _FakeRect_0( + this, + Invocation.method( + #getLocalClipBounds, + [], + ), + ), + ) as _i2.Rect); + + @override + _i2.Rect getDestinationClipBounds() => (super.noSuchMethod( + Invocation.method( + #getDestinationClipBounds, + [], + ), + returnValue: _FakeRect_0( + this, + Invocation.method( + #getDestinationClipBounds, + [], + ), + ), + ) as _i2.Rect); + + @override + void drawColor( + _i2.Color? color, + _i2.BlendMode? blendMode, + ) => + super.noSuchMethod( + Invocation.method( + #drawColor, + [ + color, + blendMode, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawLine( + _i2.Offset? p1, + _i2.Offset? p2, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawLine, + [ + p1, + p2, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawPaint(_i2.Paint? paint) => super.noSuchMethod( + Invocation.method( + #drawPaint, + [paint], + ), + returnValueForMissingStub: null, + ); + + @override + void drawRect( + _i2.Rect? rect, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawRect, + [ + rect, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawRRect( + _i2.RRect? rrect, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawRRect, + [ + rrect, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawDRRect( + _i2.RRect? outer, + _i2.RRect? inner, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawDRRect, + [ + outer, + inner, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawRSuperellipse( + _i2.RSuperellipse? rsuperellipse, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawRSuperellipse, + [ + rsuperellipse, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawOval( + _i2.Rect? rect, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawOval, + [ + rect, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawCircle( + _i2.Offset? c, + double? radius, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawCircle, + [ + c, + radius, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawArc( + _i2.Rect? rect, + double? startAngle, + double? sweepAngle, + bool? useCenter, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawArc, + [ + rect, + startAngle, + sweepAngle, + useCenter, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawPath( + _i2.Path? path, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawPath, + [ + path, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawImage( + _i2.Image? image, + _i2.Offset? offset, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawImage, + [ + image, + offset, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawImageRect( + _i2.Image? image, + _i2.Rect? src, + _i2.Rect? dst, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawImageRect, + [ + image, + src, + dst, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawImageNine( + _i2.Image? image, + _i2.Rect? center, + _i2.Rect? dst, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawImageNine, + [ + image, + center, + dst, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawPicture(_i2.Picture? picture) => super.noSuchMethod( + Invocation.method( + #drawPicture, + [picture], + ), + returnValueForMissingStub: null, + ); + + @override + void drawParagraph( + _i2.Paragraph? paragraph, + _i2.Offset? offset, + ) => + super.noSuchMethod( + Invocation.method( + #drawParagraph, + [ + paragraph, + offset, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawPoints( + _i2.PointMode? pointMode, + List<_i2.Offset>? points, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawPoints, + [ + pointMode, + points, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawRawPoints( + _i2.PointMode? pointMode, + _i5.Float32List? points, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawRawPoints, + [ + pointMode, + points, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawVertices( + _i2.Vertices? vertices, + _i2.BlendMode? blendMode, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawVertices, + [ + vertices, + blendMode, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawAtlas( + _i2.Image? atlas, + List<_i2.RSTransform>? transforms, + List<_i2.Rect>? rects, + List<_i2.Color>? colors, + _i2.BlendMode? blendMode, + _i2.Rect? cullRect, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawAtlas, + [ + atlas, + transforms, + rects, + colors, + blendMode, + cullRect, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawRawAtlas( + _i2.Image? atlas, + _i5.Float32List? rstTransforms, + _i5.Float32List? rects, + _i5.Int32List? colors, + _i2.BlendMode? blendMode, + _i2.Rect? cullRect, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawRawAtlas, + [ + atlas, + rstTransforms, + rects, + colors, + blendMode, + cullRect, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawShadow( + _i2.Path? path, + _i2.Color? color, + double? elevation, + bool? transparentOccluder, + ) => + super.noSuchMethod( + Invocation.method( + #drawShadow, + [ + path, + color, + elevation, + transparentOccluder, + ], + ), + returnValueForMissingStub: null, + ); +} + +/// A class which mocks [CanvasWrapper]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockCanvasWrapper extends _i1.Mock implements _i6.CanvasWrapper { + MockCanvasWrapper() { + _i1.throwOnMissingStub(this); + } + + @override + _i2.Canvas get canvas => (super.noSuchMethod( + Invocation.getter(#canvas), + returnValue: _FakeCanvas_1( + this, + Invocation.getter(#canvas), + ), + ) as _i2.Canvas); + + @override + _i2.Size get size => (super.noSuchMethod( + Invocation.getter(#size), + returnValue: _FakeSize_2( + this, + Invocation.getter(#size), + ), + ) as _i2.Size); + + @override + void drawRRect( + _i2.RRect? rrect, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawRRect, + [ + rrect, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void save() => super.noSuchMethod( + Invocation.method( + #save, + [], + ), + returnValueForMissingStub: null, + ); + + @override + void restore() => super.noSuchMethod( + Invocation.method( + #restore, + [], + ), + returnValueForMissingStub: null, + ); + + @override + void clipRect( + _i2.Rect? rect, { + _i2.ClipOp? clipOp = _i2.ClipOp.intersect, + bool? doAntiAlias = true, + }) => + super.noSuchMethod( + Invocation.method( + #clipRect, + [rect], + { + #clipOp: clipOp, + #doAntiAlias: doAntiAlias, + }, + ), + returnValueForMissingStub: null, + ); + + @override + void translate( + double? dx, + double? dy, + ) => + super.noSuchMethod( + Invocation.method( + #translate, + [ + dx, + dy, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void rotate(double? radius) => super.noSuchMethod( + Invocation.method( + #rotate, + [radius], + ), + returnValueForMissingStub: null, + ); + + @override + void drawPath( + _i2.Path? path, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawPath, + [ + path, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void saveLayer( + _i2.Rect? bounds, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #saveLayer, + [ + bounds, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawPicture(_i2.Picture? picture) => super.noSuchMethod( + Invocation.method( + #drawPicture, + [picture], + ), + returnValueForMissingStub: null, + ); + + @override + void drawImage( + _i2.Image? image, + _i2.Offset? offset, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawImage, + [ + image, + offset, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void clipPath( + _i2.Path? path, { + bool? doAntiAlias = true, + }) => + super.noSuchMethod( + Invocation.method( + #clipPath, + [path], + {#doAntiAlias: doAntiAlias}, + ), + returnValueForMissingStub: null, + ); + + @override + void drawRect( + _i2.Rect? rect, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawRect, + [ + rect, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawLine( + _i2.Offset? p1, + _i2.Offset? p2, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawLine, + [ + p1, + p2, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawCircle( + _i2.Offset? center, + double? radius, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawCircle, + [ + center, + radius, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawArc( + _i2.Rect? rect, + double? startAngle, + double? sweepAngle, + bool? useCenter, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawArc, + [ + rect, + startAngle, + sweepAngle, + useCenter, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawText( + _i3.TextPainter? tp, + _i2.Offset? offset, [ + double? rotateAngle, + ]) => + super.noSuchMethod( + Invocation.method( + #drawText, + [ + tp, + offset, + rotateAngle, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawVerticalText( + _i3.TextPainter? tp, + _i2.Offset? offset, [ + double? rotateAngle = 90.0, + ]) => + super.noSuchMethod( + Invocation.method( + #drawVerticalText, + [ + tp, + offset, + rotateAngle, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawDot( + _i7.FlDotPainter? painter, + _i7.FlSpot? spot, + _i2.Offset? offset, + ) => + super.noSuchMethod( + Invocation.method( + #drawDot, + [ + painter, + spot, + offset, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawErrorIndicator( + _i7.FlSpotErrorRangePainter? painter, + _i7.FlSpot? origin, + _i2.Offset? offset, + _i2.Rect? errorRelativeRect, + _i7.AxisChartData? axisData, + ) => + super.noSuchMethod( + Invocation.method( + #drawErrorIndicator, + [ + painter, + origin, + offset, + errorRelativeRect, + axisData, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawRotated({ + required _i2.Size? size, + _i2.Offset? rotationOffset = _i2.Offset.zero, + _i2.Offset? drawOffset = _i2.Offset.zero, + required double? angle, + required _i6.DrawCallback? drawCallback, + }) => + super.noSuchMethod( + Invocation.method( + #drawRotated, + [], + { + #size: size, + #rotationOffset: rotationOffset, + #drawOffset: drawOffset, + #angle: angle, + #drawCallback: drawCallback, + }, + ), + returnValueForMissingStub: null, + ); + + @override + void drawDashedLine( + _i2.Offset? from, + _i2.Offset? to, + _i2.Paint? painter, + List? dashArray, + ) => + super.noSuchMethod( + Invocation.method( + #drawDashedLine, + [ + from, + to, + painter, + dashArray, + ], + ), + returnValueForMissingStub: null, + ); +} + +/// A class which mocks [BuildContext]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockBuildContext extends _i1.Mock implements _i3.BuildContext { + MockBuildContext() { + _i1.throwOnMissingStub(this); + } + + @override + _i3.Widget get widget => (super.noSuchMethod( + Invocation.getter(#widget), + returnValue: _FakeWidget_3( + this, + Invocation.getter(#widget), + ), + ) as _i3.Widget); + + @override + bool get mounted => (super.noSuchMethod( + Invocation.getter(#mounted), + returnValue: false, + ) as bool); + + @override + bool get debugDoingBuild => (super.noSuchMethod( + Invocation.getter(#debugDoingBuild), + returnValue: false, + ) as bool); + + @override + _i3.InheritedWidget dependOnInheritedElement( + _i3.InheritedElement? ancestor, { + Object? aspect, + }) => + (super.noSuchMethod( + Invocation.method( + #dependOnInheritedElement, + [ancestor], + {#aspect: aspect}, + ), + returnValue: _FakeInheritedWidget_4( + this, + Invocation.method( + #dependOnInheritedElement, + [ancestor], + {#aspect: aspect}, + ), + ), + ) as _i3.InheritedWidget); + + @override + void visitAncestorElements(_i3.ConditionalElementVisitor? visitor) => + super.noSuchMethod( + Invocation.method( + #visitAncestorElements, + [visitor], + ), + returnValueForMissingStub: null, + ); + + @override + void visitChildElements(_i3.ElementVisitor? visitor) => super.noSuchMethod( + Invocation.method( + #visitChildElements, + [visitor], + ), + returnValueForMissingStub: null, + ); + + @override + void dispatchNotification(_i3.Notification? notification) => + super.noSuchMethod( + Invocation.method( + #dispatchNotification, + [notification], + ), + returnValueForMissingStub: null, + ); + + @override + _i3.DiagnosticsNode describeElement( + String? name, { + _i4.DiagnosticsTreeStyle? style = _i4.DiagnosticsTreeStyle.errorProperty, + }) => + (super.noSuchMethod( + Invocation.method( + #describeElement, + [name], + {#style: style}, + ), + returnValue: _FakeDiagnosticsNode_5( + this, + Invocation.method( + #describeElement, + [name], + {#style: style}, + ), + ), + ) as _i3.DiagnosticsNode); + + @override + _i3.DiagnosticsNode describeWidget( + String? name, { + _i4.DiagnosticsTreeStyle? style = _i4.DiagnosticsTreeStyle.errorProperty, + }) => + (super.noSuchMethod( + Invocation.method( + #describeWidget, + [name], + {#style: style}, + ), + returnValue: _FakeDiagnosticsNode_5( + this, + Invocation.method( + #describeWidget, + [name], + {#style: style}, + ), + ), + ) as _i3.DiagnosticsNode); + + @override + List<_i3.DiagnosticsNode> describeMissingAncestor( + {required Type? expectedAncestorType}) => + (super.noSuchMethod( + Invocation.method( + #describeMissingAncestor, + [], + {#expectedAncestorType: expectedAncestorType}, + ), + returnValue: <_i3.DiagnosticsNode>[], + ) as List<_i3.DiagnosticsNode>); + + @override + _i3.DiagnosticsNode describeOwnershipChain(String? name) => + (super.noSuchMethod( + Invocation.method( + #describeOwnershipChain, + [name], + ), + returnValue: _FakeDiagnosticsNode_5( + this, + Invocation.method( + #describeOwnershipChain, + [name], + ), + ), + ) as _i3.DiagnosticsNode); +} + +/// A class which mocks [Utils]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockUtils extends _i1.Mock implements _i8.Utils { + MockUtils() { + _i1.throwOnMissingStub(this); + } + + @override + double radians(double? degrees) => (super.noSuchMethod( + Invocation.method( + #radians, + [degrees], + ), + returnValue: 0.0, + ) as double); + + @override + double degrees(double? radians) => (super.noSuchMethod( + Invocation.method( + #degrees, + [radians], + ), + returnValue: 0.0, + ) as double); + + @override + double translateRotatedPosition( + double? size, + double? degree, + ) => + (super.noSuchMethod( + Invocation.method( + #translateRotatedPosition, + [ + size, + degree, + ], + ), + returnValue: 0.0, + ) as double); + + @override + _i2.Offset calculateRotationOffset( + _i2.Size? size, + double? degree, + ) => + (super.noSuchMethod( + Invocation.method( + #calculateRotationOffset, + [ + size, + degree, + ], + ), + returnValue: _FakeOffset_6( + this, + Invocation.method( + #calculateRotationOffset, + [ + size, + degree, + ], + ), + ), + ) as _i2.Offset); + + @override + _i3.BorderRadius? normalizeBorderRadius( + _i3.BorderRadius? borderRadius, + double? width, + ) => + (super.noSuchMethod(Invocation.method( + #normalizeBorderRadius, + [ + borderRadius, + width, + ], + )) as _i3.BorderRadius?); + + @override + _i3.BorderSide normalizeBorderSide( + _i3.BorderSide? borderSide, + double? width, + ) => + (super.noSuchMethod( + Invocation.method( + #normalizeBorderSide, + [ + borderSide, + width, + ], + ), + returnValue: _FakeBorderSide_7( + this, + Invocation.method( + #normalizeBorderSide, + [ + borderSide, + width, + ], + ), + ), + ) as _i3.BorderSide); + + @override + double getEfficientInterval( + double? axisViewSize, + double? diffInAxis, { + double? pixelPerInterval = 40.0, + }) => + (super.noSuchMethod( + Invocation.method( + #getEfficientInterval, + [ + axisViewSize, + diffInAxis, + ], + {#pixelPerInterval: pixelPerInterval}, + ), + returnValue: 0.0, + ) as double); + + @override + double roundInterval(double? input) => (super.noSuchMethod( + Invocation.method( + #roundInterval, + [input], + ), + returnValue: 0.0, + ) as double); + + @override + int getFractionDigits(double? value) => (super.noSuchMethod( + Invocation.method( + #getFractionDigits, + [value], + ), + returnValue: 0, + ) as int); + + @override + String formatNumber( + double? axisMin, + double? axisMax, + double? axisValue, + ) => + (super.noSuchMethod( + Invocation.method( + #formatNumber, + [ + axisMin, + axisMax, + axisValue, + ], + ), + returnValue: _i9.dummyValue( + this, + Invocation.method( + #formatNumber, + [ + axisMin, + axisMax, + axisValue, + ], + ), + ), + ) as String); + + @override + _i3.TextStyle getThemeAwareTextStyle( + _i3.BuildContext? context, + _i3.TextStyle? providedStyle, + ) => + (super.noSuchMethod( + Invocation.method( + #getThemeAwareTextStyle, + [ + context, + providedStyle, + ], + ), + returnValue: _FakeTextStyle_8( + this, + Invocation.method( + #getThemeAwareTextStyle, + [ + context, + providedStyle, + ], + ), + ), + ) as _i3.TextStyle); + + @override + double getBestInitialIntervalValue( + double? min, + double? max, + double? interval, { + double? baseline = 0.0, + }) => + (super.noSuchMethod( + Invocation.method( + #getBestInitialIntervalValue, + [ + min, + max, + interval, + ], + {#baseline: baseline}, + ), + returnValue: 0.0, + ) as double); + + @override + double convertRadiusToSigma(double? radius) => (super.noSuchMethod( + Invocation.method( + #convertRadiusToSigma, + [radius], + ), + returnValue: 0.0, + ) as double); +} diff --git a/test/chart/gauge_chart/gauge_chart_renderer_test.dart b/test/chart/gauge_chart/gauge_chart_renderer_test.dart new file mode 100644 index 000000000..25f5b20bf --- /dev/null +++ b/test/chart/gauge_chart/gauge_chart_renderer_test.dart @@ -0,0 +1,165 @@ +import 'package:fl_chart/fl_chart.dart'; +import 'package:fl_chart/src/chart/base/base_chart/base_chart_painter.dart'; +import 'package:fl_chart/src/chart/gauge_chart/gauge_chart_painter.dart'; +import 'package:fl_chart/src/chart/gauge_chart/gauge_chart_renderer.dart'; +import 'package:fl_chart/src/utils/canvas_wrapper.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; + +import '../data_pool.dart'; +import 'gauge_chart_renderer_test.mocks.dart'; + +@GenerateMocks([Canvas, PaintingContext, BuildContext, GaugeChartPainter]) +void main() { + group('GaugeChartRenderer', () { + GaugeChartData createData() { + return GaugeChartData( + rings: const [ + GaugeProgressRing( + value: 0.7, + color: MockData.color0, + width: 5, + backgroundColor: MockData.color6, + strokeCap: StrokeCap.round, + ), + ], + ); + } + + GaugeChartData createTargetData() { + return GaugeChartData( + rings: const [ + GaugeProgressRing( + value: 0.5, + color: MockData.color1, + width: 5, + backgroundColor: MockData.color5, + strokeCap: StrokeCap.round, + ), + ], + sweepAngle: 180, + ); + } + + const textScaler = TextScaler.linear(4); + final mockBuildContext = MockBuildContext(); + final mockPainter = MockGaugeChartPainter(); + final mockPaintingContext = MockPaintingContext(); + final mockCanvas = MockCanvas(); + const mockSize = Size(44, 44); + + setUp(() { + reset(mockPainter); + reset(mockPaintingContext); + reset(mockCanvas); + when(mockPaintingContext.canvas) + .thenAnswer((realInvocation) => mockCanvas); + }); + + test('test 1 correct data', () { + final data = createData(); + final targetData = createTargetData(); + final renderGaugeChart = RenderGaugeChart( + mockBuildContext, + data, + targetData, + textScaler, + ) + ..mockTestSize = mockSize + ..painter = mockPainter; + + expect(renderGaugeChart.data == data, true); + expect(renderGaugeChart.data == targetData, false); + expect(renderGaugeChart.targetData == targetData, true); + expect(renderGaugeChart.textScaler == textScaler, true); + expect(renderGaugeChart.paintHolder.data == data, true); + expect(renderGaugeChart.paintHolder.targetData == targetData, true); + expect(renderGaugeChart.paintHolder.textScaler == textScaler, true); + }); + + test('test 2 check paint function', () { + final data = createData(); + final targetData = createTargetData(); + RenderGaugeChart( + mockBuildContext, + data, + targetData, + textScaler, + ) + ..mockTestSize = mockSize + ..painter = mockPainter + ..paint(mockPaintingContext, const Offset(10, 10)); + + verify(mockCanvas.save()).called(1); + verify(mockCanvas.translate(10, 10)).called(1); + final result = verify(mockPainter.paint(any, captureAny, captureAny)); + expect(result.callCount, 1); + + final canvasWrapper = result.captured[0] as CanvasWrapper; + expect(canvasWrapper.size, const Size(44, 44)); + expect(canvasWrapper.canvas, mockCanvas); + + final paintHolder = result.captured[1] as PaintHolder; + expect(paintHolder.data, data); + expect(paintHolder.targetData, targetData); + expect(paintHolder.textScaler, textScaler); + + verify(mockCanvas.restore()).called(1); + }); + + test('test 3 check getResponseAtLocation function', () { + final data = createData(); + final targetData = createTargetData(); + final renderGaugeChart = RenderGaugeChart( + mockBuildContext, + data, + targetData, + textScaler, + ) + ..mockTestSize = mockSize + ..painter = mockPainter; + + final results = >[]; + when(mockPainter.handleTouch(captureAny, captureAny, captureAny)) + .thenAnswer((inv) { + results.add({ + 'local_position': inv.positionalArguments[0] as Offset, + 'size': inv.positionalArguments[1] as Size, + 'paint_holder': inv.positionalArguments[2] as PaintHolder, + }); + return gaugeTouchedRing1; + }); + final touchResponse = + renderGaugeChart.getResponseAtLocation(MockData.offset1); + expect(touchResponse.touchedRing, gaugeTouchedRing1); + expect(results[0]['local_position'] as Offset, MockData.offset1); + expect(results[0]['size'] as Size, mockSize); + final paintHolder = results[0]['paint_holder'] as PaintHolder; + expect(paintHolder.data, data); + expect(paintHolder.targetData, targetData); + expect(paintHolder.textScaler, textScaler); + }); + + test('test 4 check setters', () { + final data = createData(); + final targetData = createTargetData(); + final renderGaugeChart = RenderGaugeChart( + mockBuildContext, + data, + targetData, + textScaler, + ) + ..mockTestSize = mockSize + ..painter = mockPainter + ..data = targetData + ..targetData = data + ..textScaler = const TextScaler.linear(22); + + expect(renderGaugeChart.data, targetData); + expect(renderGaugeChart.targetData, data); + expect(renderGaugeChart.textScaler, const TextScaler.linear(22)); + }); + }); +} diff --git a/test/chart/gauge_chart/gauge_chart_renderer_test.mocks.dart b/test/chart/gauge_chart/gauge_chart_renderer_test.mocks.dart new file mode 100644 index 000000000..92dd75ebf --- /dev/null +++ b/test/chart/gauge_chart/gauge_chart_renderer_test.mocks.dart @@ -0,0 +1,1432 @@ +// Mocks generated by Mockito 5.4.6 from annotations +// in fl_chart/test/chart/gauge_chart/gauge_chart_renderer_test.dart. +// Do not manually edit this file. + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:typed_data' as _i7; +import 'dart:ui' as _i2; + +import 'package:fl_chart/fl_chart.dart' as _i13; +import 'package:fl_chart/src/chart/base/base_chart/base_chart_painter.dart' + as _i12; +import 'package:fl_chart/src/chart/gauge_chart/gauge_chart_painter.dart' + as _i10; +import 'package:fl_chart/src/utils/canvas_wrapper.dart' as _i11; +import 'package:flutter/foundation.dart' as _i5; +import 'package:flutter/gestures.dart' as _i8; +import 'package:flutter/material.dart' as _i6; +import 'package:flutter/rendering.dart' as _i3; +import 'package:flutter/src/rendering/layer.dart' as _i4; +import 'package:flutter/src/widgets/notification_listener.dart' as _i9; +import 'package:mockito/mockito.dart' as _i1; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: must_be_immutable +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class +// ignore_for_file: invalid_use_of_internal_member + +class _FakeRect_0 extends _i1.SmartFake implements _i2.Rect { + _FakeRect_0( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakePictureRecorder_1 extends _i1.SmartFake + implements _i2.PictureRecorder { + _FakePictureRecorder_1( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeCanvas_2 extends _i1.SmartFake implements _i2.Canvas { + _FakeCanvas_2( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakePaintingContext_3 extends _i1.SmartFake + implements _i3.PaintingContext { + _FakePaintingContext_3( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeColorFilterLayer_4 extends _i1.SmartFake + implements _i4.ColorFilterLayer { + _FakeColorFilterLayer_4( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); + + @override + String toString({_i5.DiagnosticLevel? minLevel = _i5.DiagnosticLevel.info}) => + super.toString(); +} + +class _FakeOpacityLayer_5 extends _i1.SmartFake implements _i4.OpacityLayer { + _FakeOpacityLayer_5( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); + + @override + String toString({_i5.DiagnosticLevel? minLevel = _i5.DiagnosticLevel.info}) => + super.toString(); +} + +class _FakeWidget_6 extends _i1.SmartFake implements _i6.Widget { + _FakeWidget_6( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); + + @override + String toString({_i5.DiagnosticLevel? minLevel = _i5.DiagnosticLevel.info}) => + super.toString(); +} + +class _FakeInheritedWidget_7 extends _i1.SmartFake + implements _i6.InheritedWidget { + _FakeInheritedWidget_7( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); + + @override + String toString({_i5.DiagnosticLevel? minLevel = _i5.DiagnosticLevel.info}) => + super.toString(); +} + +class _FakeDiagnosticsNode_8 extends _i1.SmartFake + implements _i5.DiagnosticsNode { + _FakeDiagnosticsNode_8( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); + + @override + String toString({ + _i5.TextTreeConfiguration? parentConfiguration, + _i5.DiagnosticLevel? minLevel = _i5.DiagnosticLevel.info, + }) => + super.toString(); +} + +class _FakeOffset_9 extends _i1.SmartFake implements _i2.Offset { + _FakeOffset_9( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +/// A class which mocks [Canvas]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockCanvas extends _i1.Mock implements _i2.Canvas { + MockCanvas() { + _i1.throwOnMissingStub(this); + } + + @override + void save() => super.noSuchMethod( + Invocation.method( + #save, + [], + ), + returnValueForMissingStub: null, + ); + + @override + void saveLayer( + _i2.Rect? bounds, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #saveLayer, + [ + bounds, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void restore() => super.noSuchMethod( + Invocation.method( + #restore, + [], + ), + returnValueForMissingStub: null, + ); + + @override + void restoreToCount(int? count) => super.noSuchMethod( + Invocation.method( + #restoreToCount, + [count], + ), + returnValueForMissingStub: null, + ); + + @override + int getSaveCount() => (super.noSuchMethod( + Invocation.method( + #getSaveCount, + [], + ), + returnValue: 0, + ) as int); + + @override + void translate( + double? dx, + double? dy, + ) => + super.noSuchMethod( + Invocation.method( + #translate, + [ + dx, + dy, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void scale( + double? sx, [ + double? sy, + ]) => + super.noSuchMethod( + Invocation.method( + #scale, + [ + sx, + sy, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void rotate(double? radians) => super.noSuchMethod( + Invocation.method( + #rotate, + [radians], + ), + returnValueForMissingStub: null, + ); + + @override + void skew( + double? sx, + double? sy, + ) => + super.noSuchMethod( + Invocation.method( + #skew, + [ + sx, + sy, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void transform(_i7.Float64List? matrix4) => super.noSuchMethod( + Invocation.method( + #transform, + [matrix4], + ), + returnValueForMissingStub: null, + ); + + @override + _i7.Float64List getTransform() => (super.noSuchMethod( + Invocation.method( + #getTransform, + [], + ), + returnValue: _i7.Float64List(0), + ) as _i7.Float64List); + + @override + void clipRect( + _i2.Rect? rect, { + _i2.ClipOp? clipOp = _i2.ClipOp.intersect, + bool? doAntiAlias = true, + }) => + super.noSuchMethod( + Invocation.method( + #clipRect, + [rect], + { + #clipOp: clipOp, + #doAntiAlias: doAntiAlias, + }, + ), + returnValueForMissingStub: null, + ); + + @override + void clipRRect( + _i2.RRect? rrect, { + bool? doAntiAlias = true, + }) => + super.noSuchMethod( + Invocation.method( + #clipRRect, + [rrect], + {#doAntiAlias: doAntiAlias}, + ), + returnValueForMissingStub: null, + ); + + @override + void clipRSuperellipse( + _i2.RSuperellipse? rsuperellipse, { + bool? doAntiAlias = true, + }) => + super.noSuchMethod( + Invocation.method( + #clipRSuperellipse, + [rsuperellipse], + {#doAntiAlias: doAntiAlias}, + ), + returnValueForMissingStub: null, + ); + + @override + void clipPath( + _i2.Path? path, { + bool? doAntiAlias = true, + }) => + super.noSuchMethod( + Invocation.method( + #clipPath, + [path], + {#doAntiAlias: doAntiAlias}, + ), + returnValueForMissingStub: null, + ); + + @override + _i2.Rect getLocalClipBounds() => (super.noSuchMethod( + Invocation.method( + #getLocalClipBounds, + [], + ), + returnValue: _FakeRect_0( + this, + Invocation.method( + #getLocalClipBounds, + [], + ), + ), + ) as _i2.Rect); + + @override + _i2.Rect getDestinationClipBounds() => (super.noSuchMethod( + Invocation.method( + #getDestinationClipBounds, + [], + ), + returnValue: _FakeRect_0( + this, + Invocation.method( + #getDestinationClipBounds, + [], + ), + ), + ) as _i2.Rect); + + @override + void drawColor( + _i2.Color? color, + _i2.BlendMode? blendMode, + ) => + super.noSuchMethod( + Invocation.method( + #drawColor, + [ + color, + blendMode, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawLine( + _i2.Offset? p1, + _i2.Offset? p2, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawLine, + [ + p1, + p2, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawPaint(_i2.Paint? paint) => super.noSuchMethod( + Invocation.method( + #drawPaint, + [paint], + ), + returnValueForMissingStub: null, + ); + + @override + void drawRect( + _i2.Rect? rect, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawRect, + [ + rect, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawRRect( + _i2.RRect? rrect, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawRRect, + [ + rrect, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawDRRect( + _i2.RRect? outer, + _i2.RRect? inner, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawDRRect, + [ + outer, + inner, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawRSuperellipse( + _i2.RSuperellipse? rsuperellipse, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawRSuperellipse, + [ + rsuperellipse, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawOval( + _i2.Rect? rect, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawOval, + [ + rect, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawCircle( + _i2.Offset? c, + double? radius, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawCircle, + [ + c, + radius, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawArc( + _i2.Rect? rect, + double? startAngle, + double? sweepAngle, + bool? useCenter, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawArc, + [ + rect, + startAngle, + sweepAngle, + useCenter, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawPath( + _i2.Path? path, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawPath, + [ + path, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawImage( + _i2.Image? image, + _i2.Offset? offset, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawImage, + [ + image, + offset, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawImageRect( + _i2.Image? image, + _i2.Rect? src, + _i2.Rect? dst, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawImageRect, + [ + image, + src, + dst, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawImageNine( + _i2.Image? image, + _i2.Rect? center, + _i2.Rect? dst, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawImageNine, + [ + image, + center, + dst, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawPicture(_i2.Picture? picture) => super.noSuchMethod( + Invocation.method( + #drawPicture, + [picture], + ), + returnValueForMissingStub: null, + ); + + @override + void drawParagraph( + _i2.Paragraph? paragraph, + _i2.Offset? offset, + ) => + super.noSuchMethod( + Invocation.method( + #drawParagraph, + [ + paragraph, + offset, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawPoints( + _i2.PointMode? pointMode, + List<_i2.Offset>? points, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawPoints, + [ + pointMode, + points, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawRawPoints( + _i2.PointMode? pointMode, + _i7.Float32List? points, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawRawPoints, + [ + pointMode, + points, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawVertices( + _i2.Vertices? vertices, + _i2.BlendMode? blendMode, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawVertices, + [ + vertices, + blendMode, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawAtlas( + _i2.Image? atlas, + List<_i2.RSTransform>? transforms, + List<_i2.Rect>? rects, + List<_i2.Color>? colors, + _i2.BlendMode? blendMode, + _i2.Rect? cullRect, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawAtlas, + [ + atlas, + transforms, + rects, + colors, + blendMode, + cullRect, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawRawAtlas( + _i2.Image? atlas, + _i7.Float32List? rstTransforms, + _i7.Float32List? rects, + _i7.Int32List? colors, + _i2.BlendMode? blendMode, + _i2.Rect? cullRect, + _i2.Paint? paint, + ) => + super.noSuchMethod( + Invocation.method( + #drawRawAtlas, + [ + atlas, + rstTransforms, + rects, + colors, + blendMode, + cullRect, + paint, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawShadow( + _i2.Path? path, + _i2.Color? color, + double? elevation, + bool? transparentOccluder, + ) => + super.noSuchMethod( + Invocation.method( + #drawShadow, + [ + path, + color, + elevation, + transparentOccluder, + ], + ), + returnValueForMissingStub: null, + ); +} + +/// A class which mocks [PaintingContext]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockPaintingContext extends _i1.Mock implements _i3.PaintingContext { + MockPaintingContext() { + _i1.throwOnMissingStub(this); + } + + @override + _i2.Rect get estimatedBounds => (super.noSuchMethod( + Invocation.getter(#estimatedBounds), + returnValue: _FakeRect_0( + this, + Invocation.getter(#estimatedBounds), + ), + ) as _i2.Rect); + + @override + _i2.PictureRecorder get recorder => (super.noSuchMethod( + Invocation.getter(#recorder), + returnValue: _FakePictureRecorder_1( + this, + Invocation.getter(#recorder), + ), + ) as _i2.PictureRecorder); + + @override + _i2.Canvas get canvas => (super.noSuchMethod( + Invocation.getter(#canvas), + returnValue: _FakeCanvas_2( + this, + Invocation.getter(#canvas), + ), + ) as _i2.Canvas); + + @override + void paintChild( + _i3.RenderObject? child, + _i2.Offset? offset, + ) => + super.noSuchMethod( + Invocation.method( + #paintChild, + [ + child, + offset, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void appendLayer(_i4.Layer? layer) => super.noSuchMethod( + Invocation.method( + #appendLayer, + [layer], + ), + returnValueForMissingStub: null, + ); + + @override + _i2.VoidCallback addCompositionCallback(_i4.CompositionCallback? callback) => + (super.noSuchMethod( + Invocation.method( + #addCompositionCallback, + [callback], + ), + returnValue: () {}, + ) as _i2.VoidCallback); + + @override + void stopRecordingIfNeeded() => super.noSuchMethod( + Invocation.method( + #stopRecordingIfNeeded, + [], + ), + returnValueForMissingStub: null, + ); + + @override + void setIsComplexHint() => super.noSuchMethod( + Invocation.method( + #setIsComplexHint, + [], + ), + returnValueForMissingStub: null, + ); + + @override + void setWillChangeHint() => super.noSuchMethod( + Invocation.method( + #setWillChangeHint, + [], + ), + returnValueForMissingStub: null, + ); + + @override + void addLayer(_i4.Layer? layer) => super.noSuchMethod( + Invocation.method( + #addLayer, + [layer], + ), + returnValueForMissingStub: null, + ); + + @override + void pushLayer( + _i4.ContainerLayer? childLayer, + _i3.PaintingContextCallback? painter, + _i2.Offset? offset, { + _i2.Rect? childPaintBounds, + }) => + super.noSuchMethod( + Invocation.method( + #pushLayer, + [ + childLayer, + painter, + offset, + ], + {#childPaintBounds: childPaintBounds}, + ), + returnValueForMissingStub: null, + ); + + @override + _i3.PaintingContext createChildContext( + _i4.ContainerLayer? childLayer, + _i2.Rect? bounds, + ) => + (super.noSuchMethod( + Invocation.method( + #createChildContext, + [ + childLayer, + bounds, + ], + ), + returnValue: _FakePaintingContext_3( + this, + Invocation.method( + #createChildContext, + [ + childLayer, + bounds, + ], + ), + ), + ) as _i3.PaintingContext); + + @override + _i4.ClipRectLayer? pushClipRect( + bool? needsCompositing, + _i2.Offset? offset, + _i2.Rect? clipRect, + _i3.PaintingContextCallback? painter, { + _i2.Clip? clipBehavior = _i2.Clip.hardEdge, + _i4.ClipRectLayer? oldLayer, + }) => + (super.noSuchMethod(Invocation.method( + #pushClipRect, + [ + needsCompositing, + offset, + clipRect, + painter, + ], + { + #clipBehavior: clipBehavior, + #oldLayer: oldLayer, + }, + )) as _i4.ClipRectLayer?); + + @override + _i4.ClipRRectLayer? pushClipRRect( + bool? needsCompositing, + _i2.Offset? offset, + _i2.Rect? bounds, + _i2.RRect? clipRRect, + _i3.PaintingContextCallback? painter, { + _i2.Clip? clipBehavior = _i2.Clip.antiAlias, + _i4.ClipRRectLayer? oldLayer, + }) => + (super.noSuchMethod(Invocation.method( + #pushClipRRect, + [ + needsCompositing, + offset, + bounds, + clipRRect, + painter, + ], + { + #clipBehavior: clipBehavior, + #oldLayer: oldLayer, + }, + )) as _i4.ClipRRectLayer?); + + @override + _i4.ClipRSuperellipseLayer? pushClipRSuperellipse( + bool? needsCompositing, + _i2.Offset? offset, + _i2.Rect? bounds, + _i2.RSuperellipse? clipRSuperellipse, + _i3.PaintingContextCallback? painter, { + _i2.Clip? clipBehavior = _i2.Clip.antiAlias, + _i4.ClipRSuperellipseLayer? oldLayer, + }) => + (super.noSuchMethod(Invocation.method( + #pushClipRSuperellipse, + [ + needsCompositing, + offset, + bounds, + clipRSuperellipse, + painter, + ], + { + #clipBehavior: clipBehavior, + #oldLayer: oldLayer, + }, + )) as _i4.ClipRSuperellipseLayer?); + + @override + _i4.ClipPathLayer? pushClipPath( + bool? needsCompositing, + _i2.Offset? offset, + _i2.Rect? bounds, + _i2.Path? clipPath, + _i3.PaintingContextCallback? painter, { + _i2.Clip? clipBehavior = _i2.Clip.antiAlias, + _i4.ClipPathLayer? oldLayer, + }) => + (super.noSuchMethod(Invocation.method( + #pushClipPath, + [ + needsCompositing, + offset, + bounds, + clipPath, + painter, + ], + { + #clipBehavior: clipBehavior, + #oldLayer: oldLayer, + }, + )) as _i4.ClipPathLayer?); + + @override + _i4.ColorFilterLayer pushColorFilter( + _i2.Offset? offset, + _i2.ColorFilter? colorFilter, + _i3.PaintingContextCallback? painter, { + _i4.ColorFilterLayer? oldLayer, + }) => + (super.noSuchMethod( + Invocation.method( + #pushColorFilter, + [ + offset, + colorFilter, + painter, + ], + {#oldLayer: oldLayer}, + ), + returnValue: _FakeColorFilterLayer_4( + this, + Invocation.method( + #pushColorFilter, + [ + offset, + colorFilter, + painter, + ], + {#oldLayer: oldLayer}, + ), + ), + ) as _i4.ColorFilterLayer); + + @override + _i4.TransformLayer? pushTransform( + bool? needsCompositing, + _i2.Offset? offset, + _i8.Matrix4? transform, + _i3.PaintingContextCallback? painter, { + _i4.TransformLayer? oldLayer, + }) => + (super.noSuchMethod(Invocation.method( + #pushTransform, + [ + needsCompositing, + offset, + transform, + painter, + ], + {#oldLayer: oldLayer}, + )) as _i4.TransformLayer?); + + @override + _i4.OpacityLayer pushOpacity( + _i2.Offset? offset, + int? alpha, + _i3.PaintingContextCallback? painter, { + _i4.OpacityLayer? oldLayer, + }) => + (super.noSuchMethod( + Invocation.method( + #pushOpacity, + [ + offset, + alpha, + painter, + ], + {#oldLayer: oldLayer}, + ), + returnValue: _FakeOpacityLayer_5( + this, + Invocation.method( + #pushOpacity, + [ + offset, + alpha, + painter, + ], + {#oldLayer: oldLayer}, + ), + ), + ) as _i4.OpacityLayer); + + @override + void clipPathAndPaint( + _i2.Path? path, + _i2.Clip? clipBehavior, + _i2.Rect? bounds, + _i2.VoidCallback? painter, + ) => + super.noSuchMethod( + Invocation.method( + #clipPathAndPaint, + [ + path, + clipBehavior, + bounds, + painter, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void clipRRectAndPaint( + _i2.RRect? rrect, + _i2.Clip? clipBehavior, + _i2.Rect? bounds, + _i2.VoidCallback? painter, + ) => + super.noSuchMethod( + Invocation.method( + #clipRRectAndPaint, + [ + rrect, + clipBehavior, + bounds, + painter, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void clipRSuperellipseAndPaint( + _i2.RSuperellipse? rse, + _i2.Clip? clipBehavior, + _i2.Rect? bounds, + _i2.VoidCallback? painter, + ) => + super.noSuchMethod( + Invocation.method( + #clipRSuperellipseAndPaint, + [ + rse, + clipBehavior, + bounds, + painter, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void clipRectAndPaint( + _i2.Rect? rect, + _i2.Clip? clipBehavior, + _i2.Rect? bounds, + _i2.VoidCallback? painter, + ) => + super.noSuchMethod( + Invocation.method( + #clipRectAndPaint, + [ + rect, + clipBehavior, + bounds, + painter, + ], + ), + returnValueForMissingStub: null, + ); +} + +/// A class which mocks [BuildContext]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockBuildContext extends _i1.Mock implements _i6.BuildContext { + MockBuildContext() { + _i1.throwOnMissingStub(this); + } + + @override + _i6.Widget get widget => (super.noSuchMethod( + Invocation.getter(#widget), + returnValue: _FakeWidget_6( + this, + Invocation.getter(#widget), + ), + ) as _i6.Widget); + + @override + bool get mounted => (super.noSuchMethod( + Invocation.getter(#mounted), + returnValue: false, + ) as bool); + + @override + bool get debugDoingBuild => (super.noSuchMethod( + Invocation.getter(#debugDoingBuild), + returnValue: false, + ) as bool); + + @override + _i6.InheritedWidget dependOnInheritedElement( + _i6.InheritedElement? ancestor, { + Object? aspect, + }) => + (super.noSuchMethod( + Invocation.method( + #dependOnInheritedElement, + [ancestor], + {#aspect: aspect}, + ), + returnValue: _FakeInheritedWidget_7( + this, + Invocation.method( + #dependOnInheritedElement, + [ancestor], + {#aspect: aspect}, + ), + ), + ) as _i6.InheritedWidget); + + @override + void visitAncestorElements(_i6.ConditionalElementVisitor? visitor) => + super.noSuchMethod( + Invocation.method( + #visitAncestorElements, + [visitor], + ), + returnValueForMissingStub: null, + ); + + @override + void visitChildElements(_i6.ElementVisitor? visitor) => super.noSuchMethod( + Invocation.method( + #visitChildElements, + [visitor], + ), + returnValueForMissingStub: null, + ); + + @override + void dispatchNotification(_i9.Notification? notification) => + super.noSuchMethod( + Invocation.method( + #dispatchNotification, + [notification], + ), + returnValueForMissingStub: null, + ); + + @override + _i5.DiagnosticsNode describeElement( + String? name, { + _i5.DiagnosticsTreeStyle? style = _i5.DiagnosticsTreeStyle.errorProperty, + }) => + (super.noSuchMethod( + Invocation.method( + #describeElement, + [name], + {#style: style}, + ), + returnValue: _FakeDiagnosticsNode_8( + this, + Invocation.method( + #describeElement, + [name], + {#style: style}, + ), + ), + ) as _i5.DiagnosticsNode); + + @override + _i5.DiagnosticsNode describeWidget( + String? name, { + _i5.DiagnosticsTreeStyle? style = _i5.DiagnosticsTreeStyle.errorProperty, + }) => + (super.noSuchMethod( + Invocation.method( + #describeWidget, + [name], + {#style: style}, + ), + returnValue: _FakeDiagnosticsNode_8( + this, + Invocation.method( + #describeWidget, + [name], + {#style: style}, + ), + ), + ) as _i5.DiagnosticsNode); + + @override + List<_i5.DiagnosticsNode> describeMissingAncestor( + {required Type? expectedAncestorType}) => + (super.noSuchMethod( + Invocation.method( + #describeMissingAncestor, + [], + {#expectedAncestorType: expectedAncestorType}, + ), + returnValue: <_i5.DiagnosticsNode>[], + ) as List<_i5.DiagnosticsNode>); + + @override + _i5.DiagnosticsNode describeOwnershipChain(String? name) => + (super.noSuchMethod( + Invocation.method( + #describeOwnershipChain, + [name], + ), + returnValue: _FakeDiagnosticsNode_8( + this, + Invocation.method( + #describeOwnershipChain, + [name], + ), + ), + ) as _i5.DiagnosticsNode); +} + +/// A class which mocks [GaugeChartPainter]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockGaugeChartPainter extends _i1.Mock implements _i10.GaugeChartPainter { + MockGaugeChartPainter() { + _i1.throwOnMissingStub(this); + } + + @override + _i2.Offset center(_i2.Size? size) => (super.noSuchMethod( + Invocation.method( + #center, + [size], + ), + returnValue: _FakeOffset_9( + this, + Invocation.method( + #center, + [size], + ), + ), + ) as _i2.Offset); + + @override + void paint( + _i6.BuildContext? context, + _i11.CanvasWrapper? canvasWrapper, + _i12.PaintHolder<_i13.GaugeChartData>? holder, + ) => + super.noSuchMethod( + Invocation.method( + #paint, + [ + context, + canvasWrapper, + holder, + ], + ), + returnValueForMissingStub: null, + ); + + @override + void drawSections( + _i11.CanvasWrapper? canvasWrapper, + _i12.PaintHolder<_i13.GaugeChartData>? holder, + ) => + super.noSuchMethod( + Invocation.method( + #drawSections, + [ + canvasWrapper, + holder, + ], + ), + returnValueForMissingStub: null, + ); + + @override + _i13.GaugeTouchedRing? handleTouch( + _i2.Offset? touchedPoint, + _i2.Size? viewSize, + _i12.PaintHolder<_i13.GaugeChartData>? holder, + ) => + (super.noSuchMethod(Invocation.method( + #handleTouch, + [ + touchedPoint, + viewSize, + holder, + ], + )) as _i13.GaugeTouchedRing?); + + @override + void drawTicks( + _i6.BuildContext? context, + _i11.CanvasWrapper? canvasWrapper, + _i12.PaintHolder<_i13.GaugeChartData>? holder, + ) => + super.noSuchMethod( + Invocation.method( + #drawTicks, + [ + context, + canvasWrapper, + holder, + ], + ), + returnValueForMissingStub: null, + ); +} diff --git a/test/chart/gauge_chart/gauge_chart_widget_test.dart b/test/chart/gauge_chart/gauge_chart_widget_test.dart new file mode 100644 index 000000000..4c275966a --- /dev/null +++ b/test/chart/gauge_chart/gauge_chart_widget_test.dart @@ -0,0 +1,74 @@ +import 'package:fl_chart/fl_chart.dart'; +import 'package:fl_chart/src/chart/gauge_chart/gauge_chart_renderer.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('GaugeChart widget', () { + testWidgets('builds with initial data and renders leaf', (tester) async { + final data = GaugeChartData( + rings: const [ + GaugeProgressRing(value: 0.4, color: Colors.red, width: 8), + ], + ); + + await tester.pumpWidget( + Directionality( + textDirection: TextDirection.ltr, + child: MediaQuery( + data: const MediaQueryData(), + child: GaugeChart(data), + ), + ), + ); + + expect(find.byType(GaugeChart), findsOneWidget); + expect(find.byType(GaugeChartLeaf), findsOneWidget); + }); + + testWidgets( + 'updates tween when data changes (implicit animation)', + (tester) async { + final dataA = GaugeChartData( + rings: const [ + GaugeProgressRing(value: 0.2, color: Colors.red, width: 6), + ], + sweepAngle: 180, + ); + + final dataB = GaugeChartData( + rings: const [ + GaugeProgressRing(value: 0.8, color: Colors.blue, width: 10), + ], + startDegreeOffset: 30, + ); + + Widget build(GaugeChartData d) => Directionality( + textDirection: TextDirection.ltr, + child: MediaQuery( + data: const MediaQueryData(), + child: GaugeChart( + d, + // Short animation for test speed + duration: const Duration(milliseconds: 50), + ), + ), + ); + + await tester.pumpWidget(build(dataA)); + expect(find.byType(GaugeChartLeaf), findsOneWidget); + + // Update with new data should start an implicit animation + await tester.pumpWidget(build(dataB)); + + // Advance half of the animation + await tester.pump(const Duration(milliseconds: 25)); + expect(find.byType(GaugeChartLeaf), findsOneWidget); + + // Finish the animation + await tester.pumpAndSettle(); + expect(find.byType(GaugeChartLeaf), findsOneWidget); + }, + ); + }); +} diff --git a/test/chart/line_chart/line_chart_renderer_test.mocks.dart b/test/chart/line_chart/line_chart_renderer_test.mocks.dart index 43cb44ac0..c48719b30 100644 --- a/test/chart/line_chart/line_chart_renderer_test.mocks.dart +++ b/test/chart/line_chart/line_chart_renderer_test.mocks.dart @@ -44,8 +44,9 @@ class _FakeRect_0 extends _i1.SmartFake implements _i2.Rect { ); } -class _FakeCanvas_1 extends _i1.SmartFake implements _i2.Canvas { - _FakeCanvas_1( +class _FakePictureRecorder_1 extends _i1.SmartFake + implements _i2.PictureRecorder { + _FakePictureRecorder_1( Object parent, Invocation parentInvocation, ) : super( @@ -54,9 +55,19 @@ class _FakeCanvas_1 extends _i1.SmartFake implements _i2.Canvas { ); } -class _FakePaintingContext_2 extends _i1.SmartFake +class _FakeCanvas_2 extends _i1.SmartFake implements _i2.Canvas { + _FakeCanvas_2( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakePaintingContext_3 extends _i1.SmartFake implements _i3.PaintingContext { - _FakePaintingContext_2( + _FakePaintingContext_3( Object parent, Invocation parentInvocation, ) : super( @@ -65,9 +76,9 @@ class _FakePaintingContext_2 extends _i1.SmartFake ); } -class _FakeColorFilterLayer_3 extends _i1.SmartFake +class _FakeColorFilterLayer_4 extends _i1.SmartFake implements _i4.ColorFilterLayer { - _FakeColorFilterLayer_3( + _FakeColorFilterLayer_4( Object parent, Invocation parentInvocation, ) : super( @@ -80,8 +91,8 @@ class _FakeColorFilterLayer_3 extends _i1.SmartFake super.toString(); } -class _FakeOpacityLayer_4 extends _i1.SmartFake implements _i4.OpacityLayer { - _FakeOpacityLayer_4( +class _FakeOpacityLayer_5 extends _i1.SmartFake implements _i4.OpacityLayer { + _FakeOpacityLayer_5( Object parent, Invocation parentInvocation, ) : super( @@ -94,8 +105,8 @@ class _FakeOpacityLayer_4 extends _i1.SmartFake implements _i4.OpacityLayer { super.toString(); } -class _FakeWidget_5 extends _i1.SmartFake implements _i6.Widget { - _FakeWidget_5( +class _FakeWidget_6 extends _i1.SmartFake implements _i6.Widget { + _FakeWidget_6( Object parent, Invocation parentInvocation, ) : super( @@ -108,9 +119,9 @@ class _FakeWidget_5 extends _i1.SmartFake implements _i6.Widget { super.toString(); } -class _FakeInheritedWidget_6 extends _i1.SmartFake +class _FakeInheritedWidget_7 extends _i1.SmartFake implements _i6.InheritedWidget { - _FakeInheritedWidget_6( + _FakeInheritedWidget_7( Object parent, Invocation parentInvocation, ) : super( @@ -123,9 +134,9 @@ class _FakeInheritedWidget_6 extends _i1.SmartFake super.toString(); } -class _FakeDiagnosticsNode_7 extends _i1.SmartFake +class _FakeDiagnosticsNode_8 extends _i1.SmartFake implements _i5.DiagnosticsNode { - _FakeDiagnosticsNode_7( + _FakeDiagnosticsNode_8( Object parent, Invocation parentInvocation, ) : super( @@ -141,8 +152,8 @@ class _FakeDiagnosticsNode_7 extends _i1.SmartFake super.toString(); } -class _FakePath_8 extends _i1.SmartFake implements _i2.Path { - _FakePath_8( +class _FakePath_9 extends _i1.SmartFake implements _i2.Path { + _FakePath_9( Object parent, Invocation parentInvocation, ) : super( @@ -151,8 +162,8 @@ class _FakePath_8 extends _i1.SmartFake implements _i2.Path { ); } -class _FakeOffset_9 extends _i1.SmartFake implements _i2.Offset { - _FakeOffset_9( +class _FakeOffset_10 extends _i1.SmartFake implements _i2.Offset { + _FakeOffset_10( Object parent, Invocation parentInvocation, ) : super( @@ -794,10 +805,19 @@ class MockPaintingContext extends _i1.Mock implements _i3.PaintingContext { ), ) as _i2.Rect); + @override + _i2.PictureRecorder get recorder => (super.noSuchMethod( + Invocation.getter(#recorder), + returnValue: _FakePictureRecorder_1( + this, + Invocation.getter(#recorder), + ), + ) as _i2.PictureRecorder); + @override _i2.Canvas get canvas => (super.noSuchMethod( Invocation.getter(#canvas), - returnValue: _FakeCanvas_1( + returnValue: _FakeCanvas_2( this, Invocation.getter(#canvas), ), @@ -907,7 +927,7 @@ class MockPaintingContext extends _i1.Mock implements _i3.PaintingContext { bounds, ], ), - returnValue: _FakePaintingContext_2( + returnValue: _FakePaintingContext_3( this, Invocation.method( #createChildContext, @@ -1034,7 +1054,7 @@ class MockPaintingContext extends _i1.Mock implements _i3.PaintingContext { ], {#oldLayer: oldLayer}, ), - returnValue: _FakeColorFilterLayer_3( + returnValue: _FakeColorFilterLayer_4( this, Invocation.method( #pushColorFilter, @@ -1084,7 +1104,7 @@ class MockPaintingContext extends _i1.Mock implements _i3.PaintingContext { ], {#oldLayer: oldLayer}, ), - returnValue: _FakeOpacityLayer_4( + returnValue: _FakeOpacityLayer_5( this, Invocation.method( #pushOpacity, @@ -1190,7 +1210,7 @@ class MockBuildContext extends _i1.Mock implements _i6.BuildContext { @override _i6.Widget get widget => (super.noSuchMethod( Invocation.getter(#widget), - returnValue: _FakeWidget_5( + returnValue: _FakeWidget_6( this, Invocation.getter(#widget), ), @@ -1219,7 +1239,7 @@ class MockBuildContext extends _i1.Mock implements _i6.BuildContext { [ancestor], {#aspect: aspect}, ), - returnValue: _FakeInheritedWidget_6( + returnValue: _FakeInheritedWidget_7( this, Invocation.method( #dependOnInheritedElement, @@ -1269,7 +1289,7 @@ class MockBuildContext extends _i1.Mock implements _i6.BuildContext { [name], {#style: style}, ), - returnValue: _FakeDiagnosticsNode_7( + returnValue: _FakeDiagnosticsNode_8( this, Invocation.method( #describeElement, @@ -1290,7 +1310,7 @@ class MockBuildContext extends _i1.Mock implements _i6.BuildContext { [name], {#style: style}, ), - returnValue: _FakeDiagnosticsNode_7( + returnValue: _FakeDiagnosticsNode_8( this, Invocation.method( #describeWidget, @@ -1319,7 +1339,7 @@ class MockBuildContext extends _i1.Mock implements _i6.BuildContext { #describeOwnershipChain, [name], ), - returnValue: _FakeDiagnosticsNode_7( + returnValue: _FakeDiagnosticsNode_8( this, Invocation.method( #describeOwnershipChain, @@ -1482,7 +1502,7 @@ class MockLineChartPainter extends _i1.Mock implements _i10.LineChartPainter { ], {#appendToPath: appendToPath}, ), - returnValue: _FakePath_8( + returnValue: _FakePath_9( this, Invocation.method( #generateBarPath, @@ -1516,7 +1536,7 @@ class MockLineChartPainter extends _i1.Mock implements _i10.LineChartPainter { ], {#appendToPath: appendToPath}, ), - returnValue: _FakePath_8( + returnValue: _FakePath_9( this, Invocation.method( #generateNormalBarPath, @@ -1550,7 +1570,7 @@ class MockLineChartPainter extends _i1.Mock implements _i10.LineChartPainter { ], {#appendToPath: appendToPath}, ), - returnValue: _FakePath_8( + returnValue: _FakePath_9( this, Invocation.method( #generateStepBarPath, @@ -1586,7 +1606,7 @@ class MockLineChartPainter extends _i1.Mock implements _i10.LineChartPainter { ], {#fillCompletely: fillCompletely}, ), - returnValue: _FakePath_8( + returnValue: _FakePath_9( this, Invocation.method( #generateBelowBarPath, @@ -1623,7 +1643,7 @@ class MockLineChartPainter extends _i1.Mock implements _i10.LineChartPainter { ], {#fillCompletely: fillCompletely}, ), - returnValue: _FakePath_8( + returnValue: _FakePath_9( this, Invocation.method( #generateAboveBarPath, @@ -2012,7 +2032,7 @@ class MockLineChartPainter extends _i1.Mock implements _i10.LineChartPainter { holder, ], ), - returnValue: _FakeOffset_9( + returnValue: _FakeOffset_10( this, Invocation.method( #getChartCoordinateFromPixel, diff --git a/test/chart/radar_chart/radar_chart_renderer_test.mocks.dart b/test/chart/radar_chart/radar_chart_renderer_test.mocks.dart index e088d2a5b..fbf19fc1b 100644 --- a/test/chart/radar_chart/radar_chart_renderer_test.mocks.dart +++ b/test/chart/radar_chart/radar_chart_renderer_test.mocks.dart @@ -45,8 +45,9 @@ class _FakeRect_0 extends _i1.SmartFake implements _i2.Rect { ); } -class _FakeCanvas_1 extends _i1.SmartFake implements _i2.Canvas { - _FakeCanvas_1( +class _FakePictureRecorder_1 extends _i1.SmartFake + implements _i2.PictureRecorder { + _FakePictureRecorder_1( Object parent, Invocation parentInvocation, ) : super( @@ -55,9 +56,19 @@ class _FakeCanvas_1 extends _i1.SmartFake implements _i2.Canvas { ); } -class _FakePaintingContext_2 extends _i1.SmartFake +class _FakeCanvas_2 extends _i1.SmartFake implements _i2.Canvas { + _FakeCanvas_2( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakePaintingContext_3 extends _i1.SmartFake implements _i3.PaintingContext { - _FakePaintingContext_2( + _FakePaintingContext_3( Object parent, Invocation parentInvocation, ) : super( @@ -66,9 +77,9 @@ class _FakePaintingContext_2 extends _i1.SmartFake ); } -class _FakeColorFilterLayer_3 extends _i1.SmartFake +class _FakeColorFilterLayer_4 extends _i1.SmartFake implements _i4.ColorFilterLayer { - _FakeColorFilterLayer_3( + _FakeColorFilterLayer_4( Object parent, Invocation parentInvocation, ) : super( @@ -81,8 +92,8 @@ class _FakeColorFilterLayer_3 extends _i1.SmartFake super.toString(); } -class _FakeOpacityLayer_4 extends _i1.SmartFake implements _i4.OpacityLayer { - _FakeOpacityLayer_4( +class _FakeOpacityLayer_5 extends _i1.SmartFake implements _i4.OpacityLayer { + _FakeOpacityLayer_5( Object parent, Invocation parentInvocation, ) : super( @@ -95,8 +106,8 @@ class _FakeOpacityLayer_4 extends _i1.SmartFake implements _i4.OpacityLayer { super.toString(); } -class _FakeWidget_5 extends _i1.SmartFake implements _i6.Widget { - _FakeWidget_5( +class _FakeWidget_6 extends _i1.SmartFake implements _i6.Widget { + _FakeWidget_6( Object parent, Invocation parentInvocation, ) : super( @@ -109,9 +120,9 @@ class _FakeWidget_5 extends _i1.SmartFake implements _i6.Widget { super.toString(); } -class _FakeInheritedWidget_6 extends _i1.SmartFake +class _FakeInheritedWidget_7 extends _i1.SmartFake implements _i6.InheritedWidget { - _FakeInheritedWidget_6( + _FakeInheritedWidget_7( Object parent, Invocation parentInvocation, ) : super( @@ -124,9 +135,9 @@ class _FakeInheritedWidget_6 extends _i1.SmartFake super.toString(); } -class _FakeDiagnosticsNode_7 extends _i1.SmartFake +class _FakeDiagnosticsNode_8 extends _i1.SmartFake implements _i5.DiagnosticsNode { - _FakeDiagnosticsNode_7( + _FakeDiagnosticsNode_8( Object parent, Invocation parentInvocation, ) : super( @@ -775,10 +786,19 @@ class MockPaintingContext extends _i1.Mock implements _i3.PaintingContext { ), ) as _i2.Rect); + @override + _i2.PictureRecorder get recorder => (super.noSuchMethod( + Invocation.getter(#recorder), + returnValue: _FakePictureRecorder_1( + this, + Invocation.getter(#recorder), + ), + ) as _i2.PictureRecorder); + @override _i2.Canvas get canvas => (super.noSuchMethod( Invocation.getter(#canvas), - returnValue: _FakeCanvas_1( + returnValue: _FakeCanvas_2( this, Invocation.getter(#canvas), ), @@ -888,7 +908,7 @@ class MockPaintingContext extends _i1.Mock implements _i3.PaintingContext { bounds, ], ), - returnValue: _FakePaintingContext_2( + returnValue: _FakePaintingContext_3( this, Invocation.method( #createChildContext, @@ -1015,7 +1035,7 @@ class MockPaintingContext extends _i1.Mock implements _i3.PaintingContext { ], {#oldLayer: oldLayer}, ), - returnValue: _FakeColorFilterLayer_3( + returnValue: _FakeColorFilterLayer_4( this, Invocation.method( #pushColorFilter, @@ -1065,7 +1085,7 @@ class MockPaintingContext extends _i1.Mock implements _i3.PaintingContext { ], {#oldLayer: oldLayer}, ), - returnValue: _FakeOpacityLayer_4( + returnValue: _FakeOpacityLayer_5( this, Invocation.method( #pushOpacity, @@ -1171,7 +1191,7 @@ class MockBuildContext extends _i1.Mock implements _i6.BuildContext { @override _i6.Widget get widget => (super.noSuchMethod( Invocation.getter(#widget), - returnValue: _FakeWidget_5( + returnValue: _FakeWidget_6( this, Invocation.getter(#widget), ), @@ -1200,7 +1220,7 @@ class MockBuildContext extends _i1.Mock implements _i6.BuildContext { [ancestor], {#aspect: aspect}, ), - returnValue: _FakeInheritedWidget_6( + returnValue: _FakeInheritedWidget_7( this, Invocation.method( #dependOnInheritedElement, @@ -1250,7 +1270,7 @@ class MockBuildContext extends _i1.Mock implements _i6.BuildContext { [name], {#style: style}, ), - returnValue: _FakeDiagnosticsNode_7( + returnValue: _FakeDiagnosticsNode_8( this, Invocation.method( #describeElement, @@ -1271,7 +1291,7 @@ class MockBuildContext extends _i1.Mock implements _i6.BuildContext { [name], {#style: style}, ), - returnValue: _FakeDiagnosticsNode_7( + returnValue: _FakeDiagnosticsNode_8( this, Invocation.method( #describeWidget, @@ -1300,7 +1320,7 @@ class MockBuildContext extends _i1.Mock implements _i6.BuildContext { #describeOwnershipChain, [name], ), - returnValue: _FakeDiagnosticsNode_7( + returnValue: _FakeDiagnosticsNode_8( this, Invocation.method( #describeOwnershipChain, diff --git a/test/chart/scatter_chart/scatter_chart_renderer_test.mocks.dart b/test/chart/scatter_chart/scatter_chart_renderer_test.mocks.dart index f8841448a..dae14a19e 100644 --- a/test/chart/scatter_chart/scatter_chart_renderer_test.mocks.dart +++ b/test/chart/scatter_chart/scatter_chart_renderer_test.mocks.dart @@ -45,8 +45,9 @@ class _FakeRect_0 extends _i1.SmartFake implements _i2.Rect { ); } -class _FakeCanvas_1 extends _i1.SmartFake implements _i2.Canvas { - _FakeCanvas_1( +class _FakePictureRecorder_1 extends _i1.SmartFake + implements _i2.PictureRecorder { + _FakePictureRecorder_1( Object parent, Invocation parentInvocation, ) : super( @@ -55,9 +56,19 @@ class _FakeCanvas_1 extends _i1.SmartFake implements _i2.Canvas { ); } -class _FakePaintingContext_2 extends _i1.SmartFake +class _FakeCanvas_2 extends _i1.SmartFake implements _i2.Canvas { + _FakeCanvas_2( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakePaintingContext_3 extends _i1.SmartFake implements _i3.PaintingContext { - _FakePaintingContext_2( + _FakePaintingContext_3( Object parent, Invocation parentInvocation, ) : super( @@ -66,9 +77,9 @@ class _FakePaintingContext_2 extends _i1.SmartFake ); } -class _FakeColorFilterLayer_3 extends _i1.SmartFake +class _FakeColorFilterLayer_4 extends _i1.SmartFake implements _i4.ColorFilterLayer { - _FakeColorFilterLayer_3( + _FakeColorFilterLayer_4( Object parent, Invocation parentInvocation, ) : super( @@ -81,8 +92,8 @@ class _FakeColorFilterLayer_3 extends _i1.SmartFake super.toString(); } -class _FakeOpacityLayer_4 extends _i1.SmartFake implements _i4.OpacityLayer { - _FakeOpacityLayer_4( +class _FakeOpacityLayer_5 extends _i1.SmartFake implements _i4.OpacityLayer { + _FakeOpacityLayer_5( Object parent, Invocation parentInvocation, ) : super( @@ -95,8 +106,8 @@ class _FakeOpacityLayer_4 extends _i1.SmartFake implements _i4.OpacityLayer { super.toString(); } -class _FakeWidget_5 extends _i1.SmartFake implements _i6.Widget { - _FakeWidget_5( +class _FakeWidget_6 extends _i1.SmartFake implements _i6.Widget { + _FakeWidget_6( Object parent, Invocation parentInvocation, ) : super( @@ -109,9 +120,9 @@ class _FakeWidget_5 extends _i1.SmartFake implements _i6.Widget { super.toString(); } -class _FakeInheritedWidget_6 extends _i1.SmartFake +class _FakeInheritedWidget_7 extends _i1.SmartFake implements _i6.InheritedWidget { - _FakeInheritedWidget_6( + _FakeInheritedWidget_7( Object parent, Invocation parentInvocation, ) : super( @@ -124,9 +135,9 @@ class _FakeInheritedWidget_6 extends _i1.SmartFake super.toString(); } -class _FakeDiagnosticsNode_7 extends _i1.SmartFake +class _FakeDiagnosticsNode_8 extends _i1.SmartFake implements _i5.DiagnosticsNode { - _FakeDiagnosticsNode_7( + _FakeDiagnosticsNode_8( Object parent, Invocation parentInvocation, ) : super( @@ -142,8 +153,8 @@ class _FakeDiagnosticsNode_7 extends _i1.SmartFake super.toString(); } -class _FakeOffset_8 extends _i1.SmartFake implements _i2.Offset { - _FakeOffset_8( +class _FakeOffset_9 extends _i1.SmartFake implements _i2.Offset { + _FakeOffset_9( Object parent, Invocation parentInvocation, ) : super( @@ -785,10 +796,19 @@ class MockPaintingContext extends _i1.Mock implements _i3.PaintingContext { ), ) as _i2.Rect); + @override + _i2.PictureRecorder get recorder => (super.noSuchMethod( + Invocation.getter(#recorder), + returnValue: _FakePictureRecorder_1( + this, + Invocation.getter(#recorder), + ), + ) as _i2.PictureRecorder); + @override _i2.Canvas get canvas => (super.noSuchMethod( Invocation.getter(#canvas), - returnValue: _FakeCanvas_1( + returnValue: _FakeCanvas_2( this, Invocation.getter(#canvas), ), @@ -898,7 +918,7 @@ class MockPaintingContext extends _i1.Mock implements _i3.PaintingContext { bounds, ], ), - returnValue: _FakePaintingContext_2( + returnValue: _FakePaintingContext_3( this, Invocation.method( #createChildContext, @@ -1025,7 +1045,7 @@ class MockPaintingContext extends _i1.Mock implements _i3.PaintingContext { ], {#oldLayer: oldLayer}, ), - returnValue: _FakeColorFilterLayer_3( + returnValue: _FakeColorFilterLayer_4( this, Invocation.method( #pushColorFilter, @@ -1075,7 +1095,7 @@ class MockPaintingContext extends _i1.Mock implements _i3.PaintingContext { ], {#oldLayer: oldLayer}, ), - returnValue: _FakeOpacityLayer_4( + returnValue: _FakeOpacityLayer_5( this, Invocation.method( #pushOpacity, @@ -1181,7 +1201,7 @@ class MockBuildContext extends _i1.Mock implements _i6.BuildContext { @override _i6.Widget get widget => (super.noSuchMethod( Invocation.getter(#widget), - returnValue: _FakeWidget_5( + returnValue: _FakeWidget_6( this, Invocation.getter(#widget), ), @@ -1210,7 +1230,7 @@ class MockBuildContext extends _i1.Mock implements _i6.BuildContext { [ancestor], {#aspect: aspect}, ), - returnValue: _FakeInheritedWidget_6( + returnValue: _FakeInheritedWidget_7( this, Invocation.method( #dependOnInheritedElement, @@ -1260,7 +1280,7 @@ class MockBuildContext extends _i1.Mock implements _i6.BuildContext { [name], {#style: style}, ), - returnValue: _FakeDiagnosticsNode_7( + returnValue: _FakeDiagnosticsNode_8( this, Invocation.method( #describeElement, @@ -1281,7 +1301,7 @@ class MockBuildContext extends _i1.Mock implements _i6.BuildContext { [name], {#style: style}, ), - returnValue: _FakeDiagnosticsNode_7( + returnValue: _FakeDiagnosticsNode_8( this, Invocation.method( #describeWidget, @@ -1310,7 +1330,7 @@ class MockBuildContext extends _i1.Mock implements _i6.BuildContext { #describeOwnershipChain, [name], ), - returnValue: _FakeDiagnosticsNode_7( + returnValue: _FakeDiagnosticsNode_8( this, Invocation.method( #describeOwnershipChain, @@ -1629,7 +1649,7 @@ class MockScatterChartPainter extends _i1.Mock holder, ], ), - returnValue: _FakeOffset_8( + returnValue: _FakeOffset_9( this, Invocation.method( #getChartCoordinateFromPixel,