From 1fb0c14db5b685559c88c60de980e3f8d860a2cc Mon Sep 17 00:00:00 2001 From: Xavier Schott Date: Fri, 1 Jun 2018 16:50:09 -0500 Subject: [PATCH 1/5] Fixed #26 #37 #38. Merged #35 #44. Pod 5.0.1 --- LICENSE | 2 +- README.md | 2 +- TGPControls.podspec | 6 +- TGPControls.xcodeproj/project.pbxproj | 30 ++++++--- .../xcschemes/TGPControls.xcscheme | 2 +- TGPControls/TGPCamelLabels.swift | 43 ++++--------- TGPControls/TGPControls.h | 31 ---------- TGPControls/TGPControlsTicksProtocol.swift | 29 --------- TGPControls/TGPDiscreteSlider.swift | 57 ++++++------------ TGPControlsDemo/Cartfile | 2 +- TGPControlsDemo/Podfile | 4 +- .../TGPControlsDemo.xcodeproj/project.pbxproj | 51 ++++++++++++++-- .../TGPControlsDemo/AppDelegate.swift | 20 ------ .../AppIcon.appiconset/Contents.json | 6 ++ .../AppIcon.appiconset/icon1024.png} | Bin .../Assets.xcassets/Contents.json | 6 ++ .../launch.imageset/Contents.json | 21 +++++++ .../launch.imageset/launch1024.png | Bin 0 -> 13883 bytes .../Base.lproj/LaunchScreen.storyboard | 28 +++++++-- .../Base.lproj/Main.storyboard | 55 +++++++++-------- .../TGPControlsDemo/ViewController.swift | 40 +++--------- 21 files changed, 202 insertions(+), 233 deletions(-) rename TGPControlsDemo/{icon-1024x1024.png => TGPControlsDemo/Assets.xcassets/AppIcon.appiconset/icon1024.png} (100%) create mode 100644 TGPControlsDemo/TGPControlsDemo/Assets.xcassets/Contents.json create mode 100644 TGPControlsDemo/TGPControlsDemo/Assets.xcassets/launch.imageset/Contents.json create mode 100644 TGPControlsDemo/TGPControlsDemo/Assets.xcassets/launch.imageset/launch1024.png diff --git a/LICENSE b/LICENSE index 744ac57..868de2b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2017 Xavier Schott +Copyright (c) 2018 Xavier Schott Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 80de4d1..dc17773 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Ideal to represent steps. *The discrete slider and the camel labels can work in ## Compatibility 1. Written in **Swift 3**, can be integrated with **Swift** or **Obj-C** 2. `TGPControls` are **AutoLayout**, `IB Designable` and `IB Inspectable` ready -3. Version **4.0.0** comes with a **Swift 3** demo application for **iOS 8** and above. +3. Version **5.0.1** comes with a **Swift 4** demo application for **iOS 8** and above. _**iOS 7** supported in versions 2.1.0 and earlier_ ![imagessliderdemo](https://cloud.githubusercontent.com/assets/4073988/6628373/183c7452-c8c2-11e4-9a63-107805bc0cc4.gif) diff --git a/TGPControls.podspec b/TGPControls.podspec index 4fc3e9b..a3f5c1f 100644 --- a/TGPControls.podspec +++ b/TGPControls.podspec @@ -2,7 +2,7 @@ Pod::Spec.new do |spec| # ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # spec.name = "TGPControls" - spec.version = "5.0.0" + spec.version = "5.0.1" spec.summary = "Custom animated iOS controls: Animated discrete slider, animated labels" spec.description = <<-DESC @@ -17,7 +17,7 @@ Pod::Spec.new do |spec| spec.license = { :type => "MIT", :file => "LICENSE" } # ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # - spec.author = { "Xavier Schott" => "http://swiftarchitect.com/swiftarchitect/" } + spec.author = { "Xavier Schott" => "https://www.swiftarchitect.com/swiftarchitect/" } # ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― # spec.platform = :ios @@ -25,7 +25,7 @@ Pod::Spec.new do |spec| spec.requires_arc = true # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # - spec.source = { :git => "https://github.com/SwiftArchitect/TGPControls.git", :tag => "v4.0.0" } + spec.source = { :git => "https://github.com/SwiftArchitect/TGPControls.git", :tag => "v5.0.1" } spec.source_files = "TGPControls/**/*.{swift}" spec.exclude_files = "TGPControlsDemo/*" diff --git a/TGPControls.xcodeproj/project.pbxproj b/TGPControls.xcodeproj/project.pbxproj index 8528ff5..4de76d5 100644 --- a/TGPControls.xcodeproj/project.pbxproj +++ b/TGPControls.xcodeproj/project.pbxproj @@ -99,12 +99,12 @@ DC56BDF41E46EA2000AAD0D9 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0820; + LastUpgradeCheck = 0940; ORGANIZATIONNAME = SwiftArchitect; TargetAttributes = { DC56BDFC1E46EA2000AAD0D9 = { CreatedOnToolsVersion = 8.2.1; - LastSwiftMigration = 0900; + LastSwiftMigration = 0940; ProvisioningStyle = Automatic; }; }; @@ -159,15 +159,23 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -197,8 +205,7 @@ SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_SWIFT3_OBJC_INFERENCE = Off; - SWIFT_VERSION = 4.0; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -214,15 +221,23 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -244,8 +259,7 @@ MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_SWIFT3_OBJC_INFERENCE = Off; - SWIFT_VERSION = 4.0; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; @@ -271,7 +285,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.0; }; name = Debug; @@ -293,7 +307,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.swiftarchitect.TGPControls; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; - SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.0; }; name = Release; diff --git a/TGPControls.xcodeproj/xcshareddata/xcschemes/TGPControls.xcscheme b/TGPControls.xcodeproj/xcshareddata/xcschemes/TGPControls.xcscheme index c41d331..3735ff1 100644 --- a/TGPControls.xcodeproj/xcshareddata/xcschemes/TGPControls.xcscheme +++ b/TGPControls.xcodeproj/xcshareddata/xcschemes/TGPControls.xcscheme @@ -1,6 +1,6 @@ //! Project version number for TGPControls. @@ -36,5 +7,3 @@ FOUNDATION_EXPORT double TGPControlsVersionNumber; FOUNDATION_EXPORT const unsigned char TGPControlsVersionString[]; // In this header, you should import all the public headers of your framework using statements like #import - - diff --git a/TGPControls/TGPControlsTicksProtocol.swift b/TGPControls/TGPControlsTicksProtocol.swift index 606b5ba..b333d70 100644 --- a/TGPControls/TGPControlsTicksProtocol.swift +++ b/TGPControls/TGPControlsTicksProtocol.swift @@ -1,32 +1,3 @@ -// @file: TGPControlsTicksProtocol.swift -// @project: TGPControls -// -// @author: Xavier Schott -// mailto://xschott@gmail.com -// http://thegothicparty.com -// tel://+18089383634 -// -// @license: http://opensource.org/licenses/MIT -// Copyright (c) 2017, Xavier Schott -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - import Foundation @objc public protocol TGPControlsTicksProtocol diff --git a/TGPControls/TGPDiscreteSlider.swift b/TGPControls/TGPDiscreteSlider.swift index 4606cc9..74457ba 100644 --- a/TGPControls/TGPDiscreteSlider.swift +++ b/TGPControls/TGPDiscreteSlider.swift @@ -1,32 +1,3 @@ -// @file: TGPDiscreteSlider.swift -// @project: TGPControls -// -// @author: Xavier Schott -// mailto://xschott@gmail.com -// http://thegothicparty.com -// tel://+18089383634 -// -// @license: http://opensource.org/licenses/MIT -// Copyright (c) 2017, Xavier Schott -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - import UIKit public enum ComponentStyle:Int { @@ -37,14 +8,13 @@ public enum ComponentStyle:Int { case image } - // Interface builder hides the IBInspectable for UIControl #if TARGET_INTERFACE_BUILDER public class TGPSlider_INTERFACE_BUILDER:UIView { - } +} #else // !TARGET_INTERFACE_BUILDER - public class TGPSlider_INTERFACE_BUILDER:UIControl { - } +public class TGPSlider_INTERFACE_BUILDER:UIControl { +} #endif // TARGET_INTERFACE_BUILDER @IBDesignable @@ -71,6 +41,12 @@ public class TGPDiscreteSlider:TGPSlider_INTERFACE_BUILDER { } } + @IBInspectable public var tickTintColor:UIColor? = nil { + didSet { + layoutTrack() + } + } + @IBInspectable public var tickImage:UIImage? = nil { didSet { layoutTrack() @@ -309,8 +285,9 @@ public class TGPDiscreteSlider:TGPSlider_INTERFACE_BUILDER { func drawTicks() { ticksLayer.frame = bounds - if let backgroundColor = tintColor { - ticksLayer.backgroundColor = backgroundColor.cgColor + + if let tickColor = tickTintColor ?? tintColor { + ticksLayer.backgroundColor = tickColor.cgColor } let path = UIBezierPath() @@ -500,10 +477,10 @@ public class TGPDiscreteSlider:TGPSlider_INTERFACE_BUILDER { // Shadow if(shadowRadius != 0.0) { #if TARGET_INTERFACE_BUILDER - thumbLayer.shadowOffset = CGSize(width: shadowOffset.width, - height: -shadowOffset.height) + thumbLayer.shadowOffset = CGSize(width: shadowOffset.width, + height: -shadowOffset.height) #else // !TARGET_INTERFACE_BUILDER - thumbLayer.shadowOffset = shadowOffset + thumbLayer.shadowOffset = shadowOffset #endif // TARGET_INTERFACE_BUILDER thumbLayer.shadowRadius = shadowRadius @@ -585,8 +562,8 @@ public class TGPDiscreteSlider:TGPSlider_INTERFACE_BUILDER { + (iOSThumbShadowRadius * 2) + (iOSThumbShadowOffset.width * 2), height: 28.0 - + (iOSThumbShadowRadius * 2) - + (iOSThumbShadowOffset.height * 2)) + + (iOSThumbShadowRadius * 2) + + (iOSThumbShadowOffset.height * 2)) case .image: if let thumbImage = thumbImage { diff --git a/TGPControlsDemo/Cartfile b/TGPControlsDemo/Cartfile index 1c464ce..f3a7414 100644 --- a/TGPControlsDemo/Cartfile +++ b/TGPControlsDemo/Cartfile @@ -1,2 +1,2 @@ -github "SwiftArchitect/TGPControls" == 4.0.0 +github "SwiftArchitect/TGPControls" diff --git a/TGPControlsDemo/Podfile b/TGPControlsDemo/Podfile index 8dbef95..2fe7474 100644 --- a/TGPControlsDemo/Podfile +++ b/TGPControlsDemo/Podfile @@ -3,8 +3,8 @@ platform :ios, '8.0' use_frameworks! target 'TGPControlsDemo-Pods' do - #pod 'TGPControls', :path => '../../TGPControls' - pod 'TGPControls' + pod 'TGPControls', :path => '../../TGPControls' + #pod 'TGPControls' end diff --git a/TGPControlsDemo/TGPControlsDemo.xcodeproj/project.pbxproj b/TGPControlsDemo/TGPControlsDemo.xcodeproj/project.pbxproj index 2aca661..fe49934 100644 --- a/TGPControlsDemo/TGPControlsDemo.xcodeproj/project.pbxproj +++ b/TGPControlsDemo/TGPControlsDemo.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + AC26D296425BA1D414B87647 /* Pods_TGPControlsDemo_Pods.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96ADF77D1CF3E3C9B5F25B38 /* Pods_TGPControlsDemo_Pods.framework */; }; DC4FF6431EA2E08C00BBF8E4 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC56BDC81E46DEB900AAD0D9 /* ViewController.swift */; }; DC4FF6441EA2E08C00BBF8E4 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC56BDC61E46DEB900AAD0D9 /* AppDelegate.swift */; }; DC4FF6481EA2E08C00BBF8E4 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DC56BDCF1E46DEB900AAD0D9 /* LaunchScreen.storyboard */; }; @@ -36,6 +37,9 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 860AEC28CE2BF295D5323689 /* Pods-TGPControlsDemo-Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TGPControlsDemo-Pods.debug.xcconfig"; path = "Pods/Target Support Files/Pods-TGPControlsDemo-Pods/Pods-TGPControlsDemo-Pods.debug.xcconfig"; sourceTree = ""; }; + 96ADF77D1CF3E3C9B5F25B38 /* Pods_TGPControlsDemo_Pods.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_TGPControlsDemo_Pods.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D4E7ADCD9BF439A69C180A4A /* Pods-TGPControlsDemo-Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TGPControlsDemo-Pods.release.xcconfig"; path = "Pods/Target Support Files/Pods-TGPControlsDemo-Pods/Pods-TGPControlsDemo-Pods.release.xcconfig"; sourceTree = ""; }; DC4FF6501EA2E08C00BBF8E4 /* TGPControlsDemo-Cart.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "TGPControlsDemo-Cart.app"; sourceTree = BUILT_PRODUCTS_DIR; }; DC4FF6511EA2E08C00BBF8E4 /* TGPControlsDemo-Cart-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "TGPControlsDemo-Cart-Info.plist"; sourceTree = ""; }; DC4FF6521EA2E2E700BBF8E4 /* TGPControls.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = TGPControls.framework; path = Carthage/Build/iOS/TGPControls.framework; sourceTree = ""; }; @@ -61,6 +65,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + AC26D296425BA1D414B87647 /* Pods_TGPControlsDemo_Pods.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -71,16 +76,27 @@ isa = PBXGroup; children = ( DC4FF6521EA2E2E700BBF8E4 /* TGPControls.framework */, + 96ADF77D1CF3E3C9B5F25B38 /* Pods_TGPControlsDemo_Pods.framework */, ); name = Frameworks; sourceTree = ""; }; + 90671EEB912570A269B400F1 /* Pods */ = { + isa = PBXGroup; + children = ( + 860AEC28CE2BF295D5323689 /* Pods-TGPControlsDemo-Pods.debug.xcconfig */, + D4E7ADCD9BF439A69C180A4A /* Pods-TGPControlsDemo-Pods.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; DC56BDBA1E46DEB900AAD0D9 = { isa = PBXGroup; children = ( DC56BDC51E46DEB900AAD0D9 /* TGPControlsDemo */, DC56BDC41E46DEB900AAD0D9 /* Products */, 10EC92099730DF4A939701BE /* Frameworks */, + 90671EEB912570A269B400F1 /* Pods */, ); sourceTree = ""; }; @@ -155,11 +171,12 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0820; - LastUpgradeCheck = 0820; + LastUpgradeCheck = 0940; ORGANIZATIONNAME = SwiftArchitect; TargetAttributes = { DC56BDC21E46DEB900AAD0D9 = { CreatedOnToolsVersion = 8.2.1; + LastSwiftMigration = 0940; ProvisioningStyle = Automatic; }; }; @@ -213,13 +230,16 @@ files = ( ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-TGPControlsDemo-Pods-checkManifestLockResult.txt", ); 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"; + 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; }; 3FF2E09CAFA7D92A488FACF7 /* [CP] Copy Pods Resources */ = { @@ -243,9 +263,12 @@ files = ( ); inputPaths = ( + "${SRCROOT}/Pods/Target Support Files/Pods-TGPControlsDemo-Pods/Pods-TGPControlsDemo-Pods-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/TGPControls/TGPControls.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/TGPControls.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -341,15 +364,23 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -392,15 +423,23 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -428,6 +467,7 @@ }; DC56BDD61E46DEB900AAD0D9 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 860AEC28CE2BF295D5323689 /* Pods-TGPControlsDemo-Pods.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)"; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; @@ -436,12 +476,14 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.swiftarchitect.TGPControlsDemo; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; }; name = Debug; }; DC56BDD71E46DEB900AAD0D9 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = D4E7ADCD9BF439A69C180A4A /* Pods-TGPControlsDemo-Pods.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)"; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; @@ -450,7 +492,8 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.swiftarchitect.TGPControlsDemo; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; }; name = Release; }; diff --git a/TGPControlsDemo/TGPControlsDemo/AppDelegate.swift b/TGPControlsDemo/TGPControlsDemo/AppDelegate.swift index ce93ae0..b304ae1 100644 --- a/TGPControlsDemo/TGPControlsDemo/AppDelegate.swift +++ b/TGPControlsDemo/TGPControlsDemo/AppDelegate.swift @@ -1,23 +1,3 @@ -// Copyright (c) 2017, Xavier Schott -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - import UIKit @UIApplicationMain diff --git a/TGPControlsDemo/TGPControlsDemo/Assets.xcassets/AppIcon.appiconset/Contents.json b/TGPControlsDemo/TGPControlsDemo/Assets.xcassets/AppIcon.appiconset/Contents.json index f04f616..d79278b 100644 --- a/TGPControlsDemo/TGPControlsDemo/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/TGPControlsDemo/TGPControlsDemo/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -88,6 +88,12 @@ "idiom" : "ipad", "filename" : "icon167.png", "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "icon1024.png", + "scale" : "1x" } ], "info" : { diff --git a/TGPControlsDemo/icon-1024x1024.png b/TGPControlsDemo/TGPControlsDemo/Assets.xcassets/AppIcon.appiconset/icon1024.png similarity index 100% rename from TGPControlsDemo/icon-1024x1024.png rename to TGPControlsDemo/TGPControlsDemo/Assets.xcassets/AppIcon.appiconset/icon1024.png diff --git a/TGPControlsDemo/TGPControlsDemo/Assets.xcassets/Contents.json b/TGPControlsDemo/TGPControlsDemo/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/TGPControlsDemo/TGPControlsDemo/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/TGPControlsDemo/TGPControlsDemo/Assets.xcassets/launch.imageset/Contents.json b/TGPControlsDemo/TGPControlsDemo/Assets.xcassets/launch.imageset/Contents.json new file mode 100644 index 0000000..d41570a --- /dev/null +++ b/TGPControlsDemo/TGPControlsDemo/Assets.xcassets/launch.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "launch1024.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/TGPControlsDemo/TGPControlsDemo/Assets.xcassets/launch.imageset/launch1024.png b/TGPControlsDemo/TGPControlsDemo/Assets.xcassets/launch.imageset/launch1024.png new file mode 100644 index 0000000000000000000000000000000000000000..0264bc268313a422f3b60031dd69385d858d5f56 GIT binary patch literal 13883 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 - + + + + + - + + @@ -16,12 +20,26 @@ - + + + + + + + + + + + + - + + + + diff --git a/TGPControlsDemo/TGPControlsDemo/Base.lproj/Main.storyboard b/TGPControlsDemo/TGPControlsDemo/Base.lproj/Main.storyboard index e1ad42a..ce318ba 100755 --- a/TGPControlsDemo/TGPControlsDemo/Base.lproj/Main.storyboard +++ b/TGPControlsDemo/TGPControlsDemo/Base.lproj/Main.storyboard @@ -1,11 +1,11 @@ - + - + @@ -14,7 +14,7 @@ - + @@ -27,16 +27,16 @@ - + - + @@ -68,7 +68,7 @@ - + @@ -102,7 +102,7 @@ - + @@ -140,7 +140,7 @@ - + @@ -181,13 +181,13 @@ - + @@ -219,7 +219,7 @@ - + @@ -255,13 +255,13 @@ - + @@ -294,19 +294,19 @@ - + - + - + @@ -339,13 +339,13 @@ - + @@ -381,20 +381,20 @@ - - + + + + @@ -438,6 +441,7 @@ + @@ -449,6 +453,7 @@ + @@ -498,7 +503,7 @@ - + diff --git a/TGPControlsDemo/TGPControlsDemo/ViewController.swift b/TGPControlsDemo/TGPControlsDemo/ViewController.swift index 49d3a62..05000f2 100644 --- a/TGPControlsDemo/TGPControlsDemo/ViewController.swift +++ b/TGPControlsDemo/TGPControlsDemo/ViewController.swift @@ -1,23 +1,3 @@ -// Copyright (c) 2017, Xavier Schott -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - import UIKit import TGPControls @@ -77,34 +57,34 @@ class ViewController: UIViewController { // MARK: - UIControlEvents - func touchDown(_ sender: UIControl, event:UIEvent) { + @objc func touchDown(_ sender: UIControl, event:UIEvent) { controlEventsLabel.text = "touchDown" } - func touchDownRepeat(_ sender: UIControl, event:UIEvent) { + @objc func touchDownRepeat(_ sender: UIControl, event:UIEvent) { controlEventsLabel.text = "touchDownRepeat" } - func touchDragInside(_ sender: UIControl, event:UIEvent) { + @objc func touchDragInside(_ sender: UIControl, event:UIEvent) { controlEventsLabel.text = "touchDragInside" } - func touchDragOutside(_ sender: UIControl, event:UIEvent) { + @objc func touchDragOutside(_ sender: UIControl, event:UIEvent) { controlEventsLabel.text = "touchDragOutside" } - func touchDragEnter(_ sender: UIControl, event:UIEvent) { + @objc func touchDragEnter(_ sender: UIControl, event:UIEvent) { controlEventsLabel.text = "touchDragEnter" } - func touchDragExit(_ sender: UIControl, event:UIEvent) { + @objc func touchDragExit(_ sender: UIControl, event:UIEvent) { controlEventsLabel.text = "touchDragExit" } - func touchUpInside(_ sender: UIControl, event:UIEvent) { + @objc func touchUpInside(_ sender: UIControl, event:UIEvent) { controlEventsLabel.text = "touchUpInside" } - func touchUpOutside(_ sender: UIControl, event:UIEvent) { + @objc func touchUpOutside(_ sender: UIControl, event:UIEvent) { controlEventsLabel.text = "touchUpOutside" } - func touchCancel(_ sender: UIControl, event:UIEvent) { + @objc func touchCancel(_ sender: UIControl, event:UIEvent) { controlEventsLabel.text = "touchCancel" } - func valueChanged(_ sender: TGPDiscreteSlider, event:UIEvent) { + @objc func valueChanged(_ sender: TGPDiscreteSlider, event:UIEvent) { controlEventsLabel.text = "valueChanged" stepper.value = Double(sender.value) } From af5a506b29132d70dc9a702d6a879d4252897e81 Mon Sep 17 00:00:00 2001 From: Xavier Schott Date: Fri, 1 Jun 2018 17:01:56 -0500 Subject: [PATCH 2/5] Release version 5.0.1 --- TGPControls.podspec | 1 + 1 file changed, 1 insertion(+) diff --git a/TGPControls.podspec b/TGPControls.podspec index a3f5c1f..5731bfc 100644 --- a/TGPControls.podspec +++ b/TGPControls.podspec @@ -23,6 +23,7 @@ Pod::Spec.new do |spec| spec.platform = :ios spec.ios.deployment_target = '8.0' spec.requires_arc = true + spec.swift_version = '4.0' # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # spec.source = { :git => "https://github.com/SwiftArchitect/TGPControls.git", :tag => "v5.0.1" } From 799ac4c9265dcf6f82c380dc50cc879718594d89 Mon Sep 17 00:00:00 2001 From: Xavier Schott Date: Fri, 1 Jun 2018 17:48:51 -0500 Subject: [PATCH 3/5] Swift 4.1 --- TGPControlsDemo/TGPControlsDemo.xcodeproj/project.pbxproj | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/TGPControlsDemo/TGPControlsDemo.xcodeproj/project.pbxproj b/TGPControlsDemo/TGPControlsDemo.xcodeproj/project.pbxproj index fe49934..8b6cd99 100644 --- a/TGPControlsDemo/TGPControlsDemo.xcodeproj/project.pbxproj +++ b/TGPControlsDemo/TGPControlsDemo.xcodeproj/project.pbxproj @@ -332,7 +332,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.swiftarchitect.TGPControlsDemo; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; }; name = Debug; }; @@ -350,7 +350,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.swiftarchitect.TGPControlsDemo; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; }; name = Release; }; @@ -409,6 +409,7 @@ SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -460,6 +461,7 @@ MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; From 2d830d4c828867f8bc31a0d84b330bf9f2526397 Mon Sep 17 00:00:00 2001 From: Xavier Schott Date: Fri, 1 Jun 2018 17:50:58 -0500 Subject: [PATCH 4/5] Release version 5.0.2 --- TGPControls.podspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TGPControls.podspec b/TGPControls.podspec index 5731bfc..732d1c9 100644 --- a/TGPControls.podspec +++ b/TGPControls.podspec @@ -2,7 +2,7 @@ Pod::Spec.new do |spec| # ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # spec.name = "TGPControls" - spec.version = "5.0.1" + spec.version = "5.0.2" spec.summary = "Custom animated iOS controls: Animated discrete slider, animated labels" spec.description = <<-DESC @@ -26,7 +26,7 @@ Pod::Spec.new do |spec| spec.swift_version = '4.0' # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # - spec.source = { :git => "https://github.com/SwiftArchitect/TGPControls.git", :tag => "v5.0.1" } + spec.source = { :git => "https://github.com/SwiftArchitect/TGPControls.git", :tag => "v5.0.2" } spec.source_files = "TGPControls/**/*.{swift}" spec.exclude_files = "TGPControlsDemo/*" From 8e446b1c93a9b19d7df9f478a65bbff377367ba7 Mon Sep 17 00:00:00 2001 From: Xavier Schott Date: Mon, 4 Jun 2018 22:15:27 -0700 Subject: [PATCH 5/5] Fixed #47. Fixed #48 --- README.md | 19 +++-- TGPControls.podspec | 4 +- TGPControls/TGPCamelLabels.swift | 42 ++++++++--- TGPControls/TGPDiscreteSlider.swift | 73 ++++++++++++------- .../TGPControlsDemo.xcodeproj/project.pbxproj | 37 ++++++++++ .../Base.lproj/InfoPlist.strings | 2 + .../Base.lproj/Localizable.strings | 15 ++++ .../TGPControlsDemo-Cart-Info.plist | 4 +- .../TGPControlsDemo-Pods-Info.plist | 4 +- .../TGPControlsDemo/ViewController.swift | 31 ++++++-- .../ar.lproj/InfoPlist.strings | 2 + .../ar.lproj/Localizable.strings | 15 ++++ .../TGPControlsDemo/ar.lproj/Main.strings | 15 ++++ 13 files changed, 211 insertions(+), 52 deletions(-) create mode 100644 TGPControlsDemo/TGPControlsDemo/Base.lproj/InfoPlist.strings create mode 100644 TGPControlsDemo/TGPControlsDemo/Base.lproj/Localizable.strings create mode 100644 TGPControlsDemo/TGPControlsDemo/ar.lproj/InfoPlist.strings create mode 100644 TGPControlsDemo/TGPControlsDemo/ar.lproj/Localizable.strings create mode 100644 TGPControlsDemo/TGPControlsDemo/ar.lproj/Main.strings diff --git a/README.md b/README.md index dc17773..a089394 100644 --- a/README.md +++ b/README.md @@ -22,10 +22,11 @@ Ideal to select individual steps, star rating, integers, rainbow colors, slices Ideal to represent steps. *The discrete slider and the camel labels can work in unison.* ## Compatibility -1. Written in **Swift 3**, can be integrated with **Swift** or **Obj-C** +1. Written in **Swift 4**, can be integrated with **Swift** or **Obj-C** 2. `TGPControls` are **AutoLayout**, `IB Designable` and `IB Inspectable` ready -3. Version **5.0.1** comes with a **Swift 4** demo application for **iOS 8** and above. +3. Version **5.0.1** and better comes with a **Swift 4** demo application for **iOS 8** and above. _**iOS 7** supported in versions 2.1.0 and earlier_ +4. Automatic support for both left-to-right and right-to-left languages ![imagessliderdemo](https://cloud.githubusercontent.com/assets/4073988/6628373/183c7452-c8c2-11e4-9a63-107805bc0cc4.gif) @@ -82,7 +83,9 @@ All graphic aspects, such as physical spacing of the ticks or physical width of ``` discreteSlider.ticksListener = camelLabels ``` + ![complete](https://cloud.githubusercontent.com/assets/4073988/5912616/26cf1b0a-a58b-11e4-92f7-f9dbcd53c413.gif) + That's all! Through the `TGPControlsTicksProtocol`, the camelLabels listen to _value_ and _size_ changes. You may want to adopt this protocol to handle changes, or use the traditional `UIControl` notifications: @@ -118,13 +121,16 @@ self.stepper.value = Double(sender.value) | Tick | | |:-----| ----- | +| `tickStyle` | See style property | | `tickSize` | absolute dimension | -| `tickImage` | a `UIImage`, fits in `tickSize` (†) | | `tickCount` | discrete steps, must be 2 or greater | +| `tickTintColor` | takes precedence over the control `tintColor` | +| `tickImage` | a `UIImage`, fits in `tickSize` (†) | | `ticksDistance` | horizontal spacing _(calculated)_ | | Track | | |:------| ----- | +| `trackStyle` | See style property | | `trackThickness` | height | | `trackImage` | a `UIImage`, ignores `trackThickness` (†) | | `minimumTrackTintColor` | track lower side | @@ -132,9 +138,10 @@ self.stepper.value = Double(sender.value) | Thumb | | |:------| ----- | +| `thumbStyle` | See style property | | `thumbSize` | absolute size | -| `thumbImage` | a`UIImage`, dictates `thumbSize` (†) | | `thumbTintColor` | background | +| `thumbImage` | a`UIImage`, dictates `thumbSize` (†) | | `thumbShadowRadius` | breaking the _flat design concept_ | | `thumbShadowOffset` | applied to `thumbShadowRadius`, may affect control bounds | @@ -159,8 +166,9 @@ Most of the customization can be done inside **Interface Builder**. | Property | | |:---------| ----- | -| `ticksListener` | ties a discrete slider to its camel labels. This is your most robust method to not only ensure that the layout of both controls match exactly, but also adjust this spacing when orientation changes. A typical use may be `discreteSlider.ticksListener = camelLabels` | +| `tickCount` | **design only** (_preferrably not to be used_): the number of ticks is driven by the number of elements in the `names` array | | `names` | supplies a new set of labels ; supersedes the `tickCount` property, which will return the number of labels. A typical use may be `camelLabels.names = ["OFF", "ON"]` | +| `ticksListener` | ties a discrete slider to its camel labels. This is your most robust method to not only ensure that the layout of both controls match exactly, but also adjust this spacing when orientation changes. A typical use may be `discreteSlider.ticksListener = camelLabels` | | `ticksDistance` | _override_ the labels spacing entirely ; **prefer** the `ticksListener` mechanism if it is available to you. A typical use may be `camelLabels.ticksDistance = 15` | | `value` | which label is emphasized (_selected_) | | `backgroundColor` | labels become *tap-through* (**click-through**) when set to `UIColor.clear` ; use TGPCamelLabels *on top of* other UI elements, **even native iOS objects**!(*) | @@ -170,6 +178,7 @@ Most of the customization can be done inside **Interface Builder**. | Edges & Animation | | |:------------------| ----- | +| `numberOfLiness` | Support for multiple lines labels | | `offCenter` | **leftmost and righmost labels only**: relative inset expressed as a proportion of individual label width: 0: none, +0.5: nudge in by a half width (fully fit) or -0.5: draw completely outside | | `insets` | **leftmost and righmost labels only**: absolute inset expressed in pixels | | `emphasisLayout` | emphasized (_selected_) labels vertical alignment ; `.top`, `.centerY` or `.bottom`. Default is `.top` (‡) | diff --git a/TGPControls.podspec b/TGPControls.podspec index 732d1c9..543aa6d 100644 --- a/TGPControls.podspec +++ b/TGPControls.podspec @@ -2,7 +2,7 @@ Pod::Spec.new do |spec| # ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # spec.name = "TGPControls" - spec.version = "5.0.2" + spec.version = "5.0.3" spec.summary = "Custom animated iOS controls: Animated discrete slider, animated labels" spec.description = <<-DESC @@ -26,7 +26,7 @@ Pod::Spec.new do |spec| spec.swift_version = '4.0' # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # - spec.source = { :git => "https://github.com/SwiftArchitect/TGPControls.git", :tag => "v5.0.2" } + spec.source = { :git => "https://github.com/SwiftArchitect/TGPControls.git", :tag => "v5.0.3" } spec.source_files = "TGPControls/**/*.{swift}" spec.exclude_files = "TGPControlsDemo/*" diff --git a/TGPControls/TGPCamelLabels.swift b/TGPControls/TGPCamelLabels.swift index 08cea98..d51d7d1 100644 --- a/TGPControls/TGPCamelLabels.swift +++ b/TGPControls/TGPCamelLabels.swift @@ -78,11 +78,11 @@ public class TGPCamelLabels: TGPCamelLabels_INTERFACE_BUILDER { } } - @IBInspectable public var numberOfLinesInLabel:Int = 1 { - didSet { - layoutTrack() - } - } + @IBInspectable public var numberOfLinesInLabel:Int = 1 { + didSet { + layoutTrack() + } + } // Label off-center to the left and right of the slider // expressed in label width. 0: none, -1/2: half outside, 1/2; half inside @@ -166,6 +166,7 @@ public class TGPCamelLabels: TGPCamelLabels_INTERFACE_BUILDER { var lastValue = NSNotFound var emphasizedLabels:[UILabel] = [] var regularLabels:[UILabel] = [] + var localeCharacterDirection = CFLocaleLanguageDirection.leftToRight // MARK: UIView @@ -195,6 +196,11 @@ public class TGPCamelLabels: TGPCamelLabels_INTERFACE_BUILDER { // MARK: TGPCamelLabels func initProperties() { + if let systemLocale = CFLocaleCopyCurrent(), + let localeIdentifier = CFLocaleGetIdentifier(systemLocale) { + localeCharacterDirection = CFLocaleGetLanguageCharacterDirection(localeIdentifier.rawValue) + } + debugNames(count: 10) layoutTrack() } @@ -234,10 +240,16 @@ public class TGPCamelLabels: TGPCamelLabels_INTERFACE_BUILDER { let count = names.count if count > 0 { var centerX = (bounds.width - (CGFloat(count - 1) * ticksDistance))/2.0 + if .rightToLeft == localeCharacterDirection { + centerX = bounds.width - centerX + } + let tickSpacing = (.rightToLeft == localeCharacterDirection) + ? -ticksDistance + : ticksDistance let centerY = bounds.height / 2.0 for name in names { let upLabel = UILabel.init() - upLabel.numberOfLines = self.numberOfLinesInLabel + upLabel.numberOfLines = numberOfLinesInLabel emphasizedLabels.append(upLabel) upLabel.text = name if let upFontName = upFontName { @@ -261,7 +273,7 @@ public class TGPCamelLabels: TGPCamelLabels_INTERFACE_BUILDER { addSubview(upLabel) let dnLabel = UILabel.init() - dnLabel.numberOfLines = self.numberOfLinesInLabel + dnLabel.numberOfLines = numberOfLinesInLabel regularLabels.append(dnLabel) dnLabel.text = name if let downFontName = downFontName { @@ -279,15 +291,21 @@ public class TGPCamelLabels: TGPCamelLabels_INTERFACE_BUILDER { }() addSubview(dnLabel) - centerX += ticksDistance + centerX += tickSpacing } // Fix left and right label, if there are at least 2 labels if names.count > 1 { - insetLabel(emphasizedLabels.first, withInset: insets, andMultiplier: offCenter) - insetLabel(emphasizedLabels.last, withInset: -insets, andMultiplier: -offCenter) - insetLabel(regularLabels.first, withInset: insets, andMultiplier: offCenter) - insetLabel(regularLabels.last, withInset: -insets, andMultiplier: -offCenter) + let localeInsets = (.rightToLeft == localeCharacterDirection) + ? -insets + : insets + let localeOffCenter = (.rightToLeft == localeCharacterDirection) + ? -offCenter + : offCenter + insetLabel(emphasizedLabels.first, withInset: localeInsets, andMultiplier: localeOffCenter) + insetLabel(emphasizedLabels.last, withInset: -localeInsets, andMultiplier: -localeOffCenter) + insetLabel(regularLabels.first, withInset: localeInsets, andMultiplier: localeOffCenter) + insetLabel(regularLabels.last, withInset: -localeInsets, andMultiplier: -localeOffCenter) } dockEffect(duration:0.0) diff --git a/TGPControls/TGPDiscreteSlider.swift b/TGPControls/TGPDiscreteSlider.swift index 74457ba..9ce1a59 100644 --- a/TGPControls/TGPDiscreteSlider.swift +++ b/TGPControls/TGPDiscreteSlider.swift @@ -208,7 +208,6 @@ public class TGPDiscreteSlider:TGPSlider_INTERFACE_BUILDER { let segments = CGFloat(max(1, tickCount - 1)) return trackRectangle.width / segments } - set {} } @objc public var ticksListener:TGPControlsTicksProtocol? = nil { @@ -221,15 +220,18 @@ public class TGPDiscreteSlider:TGPSlider_INTERFACE_BUILDER { var intValue:Int = 0 var intMinimumValue = -5 - var ticksAbscisses:[CGPoint] = [] - var thumbAbscisse:CGFloat = 0 + var ticksAbscissae:[CGPoint] = [] + var thumbAbscissa:CGFloat = 0 var thumbLayer = CALayer() var leftTrackLayer = CALayer() var rightTrackLayer = CALayer() var trackLayer = CALayer() + var leadingTrackLayer: CALayer! + var trailingTrackLayer: CALayer! var ticksLayer = CALayer() var trackRectangle = CGRect.zero var touchedInside = false + var localeCharacterDirection = CFLocaleLanguageDirection.leftToRight let iOSThumbShadowRadius:CGFloat = 4 let iOSThumbShadowOffset = CGSize(width:0, height:3) @@ -262,17 +264,30 @@ public class TGPDiscreteSlider:TGPSlider_INTERFACE_BUILDER { // MARK: TGPDiscreteSlider func initProperties() { + if let systemLocale = CFLocaleCopyCurrent(), + let localeIdentifier = CFLocaleGetIdentifier(systemLocale) { + localeCharacterDirection = CFLocaleGetLanguageCharacterDirection(localeIdentifier.rawValue) + } + + leadingTrackLayer = (.rightToLeft == localeCharacterDirection) + ? rightTrackLayer + : leftTrackLayer + trailingTrackLayer = (.rightToLeft == localeCharacterDirection) + ? leftTrackLayer + : rightTrackLayer + // Track is a clear clipping layer, and left + right sublayers, which brings in free animation trackLayer.masksToBounds = true trackLayer.backgroundColor = UIColor.clear.cgColor layer.addSublayer(trackLayer) - if let backgroundColor = tintColor { - leftTrackLayer.backgroundColor = backgroundColor.cgColor - } trackLayer.addSublayer(leftTrackLayer) - rightTrackLayer.backgroundColor = maximumTrackTintColor.cgColor trackLayer.addSublayer(rightTrackLayer) + if let backgroundColor = tintColor { + leadingTrackLayer.backgroundColor = backgroundColor.cgColor + } + rightTrackLayer.backgroundColor = maximumTrackTintColor.cgColor + // Ticks in between track and thumb layer.addSublayer(ticksLayer) @@ -300,7 +315,7 @@ public class TGPDiscreteSlider:TGPSlider_INTERFACE_BUILDER { fallthrough case .image: - for originPoint in ticksAbscisses { + for originPoint in ticksAbscissae { let rectangle = CGRect(x: originPoint.x-(tickSize.width/2), y: originPoint.y-(tickSize.height/2), width: tickSize.width, @@ -391,21 +406,21 @@ public class TGPDiscreteSlider:TGPSlider_INTERFACE_BUILDER { leftTrackLayer.frame = { var frame = trackLayer.bounds - frame.size.width = thumbAbscisse - trackRectangle.minX + frame.size.width = thumbAbscissa - trackRectangle.minX return frame }() - if let backgroundColor = minimumTrackTintColor ?? tintColor { - leftTrackLayer.backgroundColor = backgroundColor.cgColor - } - rightTrackLayer.frame = { var frame = trackLayer.bounds frame.size.width = trackRectangle.width - leftTrackLayer.frame.width frame.origin.x = leftTrackLayer.frame.maxX return frame }() - rightTrackLayer.backgroundColor = maximumTrackTintColor.cgColor + + if let backgroundColor = minimumTrackTintColor ?? tintColor { + leadingTrackLayer.backgroundColor = backgroundColor.cgColor + } + trailingTrackLayer.backgroundColor = maximumTrackTintColor.cgColor } func drawThumb() { @@ -414,7 +429,7 @@ public class TGPDiscreteSlider:TGPSlider_INTERFACE_BUILDER { let thumbSizeForStyle = thumbSizeIncludingShadow() let thumbWidth = thumbSizeForStyle.width let thumbHeight = thumbSizeForStyle.height - let rectangle = CGRect(x:thumbAbscisse - (thumbWidth / 2), + let rectangle = CGRect(x:thumbAbscissa - (thumbWidth / 2), y: (frame.height - thumbHeight)/2, width: thumbWidth, height: thumbHeight) @@ -515,11 +530,11 @@ public class TGPDiscreteSlider:TGPSlider_INTERFACE_BUILDER { width: trackSize.width, height: trackSize.height) let trackY = frame.height / 2 - ticksAbscisses = [] + ticksAbscissae = [] for iterate in 0 ... segments { let ratio = Double(iterate) / Double(segments) let originX = trackRectangle.origin.x + (CGFloat)(trackSize.width * CGFloat(ratio)) - ticksAbscisses.append(CGPoint(x: originX, y: trackY)) + ticksAbscissae.append(CGPoint(x: originX, y: trackY)) } layoutThumb() @@ -536,7 +551,10 @@ public class TGPDiscreteSlider:TGPSlider_INTERFACE_BUILDER { let nonZeroIncrement = ((0 == incrementValue) ? 1 : incrementValue) var thumbRatio = Double(value - minimumValue) / Double(segments * nonZeroIncrement) thumbRatio = max(0.0, min(thumbRatio, 1.0)) // Normalized - thumbAbscisse = trackRectangle.origin.x + (CGFloat)(trackRectangle.width * CGFloat(thumbRatio)) + thumbRatio = (.rightToLeft == localeCharacterDirection) + ? 1.0 - thumbRatio + : thumbRatio + thumbAbscissa = trackRectangle.origin.x + (CGFloat)(trackRectangle.width * CGFloat(thumbRatio)) } func thumbSizeIncludingShadow() -> CGSize { @@ -628,14 +646,14 @@ public class TGPDiscreteSlider:TGPSlider_INTERFACE_BUILDER { func touchDown(_ touches: Set, animationDuration duration:TimeInterval) { if let touch = touches.first { let location = touch.location(in: touch.view) - moveThumbTo(abscisse: location.x, animationDuration: duration) + moveThumbTo(abscissa: location.x, animationDuration: duration) } } func touchUp(_ touches: Set) { if let touch = touches.first { let location = touch.location(in: touch.view) - let tick = pickTickFromSliderPosition(abscisse: location.x) + let tick = pickTickFromSliderPosition(abscissa: location.x) moveThumbToTick(tick: tick) } } @@ -665,14 +683,14 @@ public class TGPDiscreteSlider:TGPSlider_INTERFACE_BUILDER { setNeedsDisplay() } - func moveThumbTo(abscisse:CGFloat, animationDuration duration:TimeInterval) { + func moveThumbTo(abscissa:CGFloat, animationDuration duration:TimeInterval) { let leftMost = trackRectangle.minX let rightMost = trackRectangle.maxX - thumbAbscisse = max(leftMost, min(abscisse, rightMost)) + thumbAbscissa = max(leftMost, min(abscissa, rightMost)) CATransaction.setAnimationDuration(duration) - let tick = pickTickFromSliderPosition(abscisse: thumbAbscisse) + let tick = pickTickFromSliderPosition(abscissa: thumbAbscissa) let nonZeroIncrement = ((0 == incrementValue) ? 1 : incrementValue) let intValue = Int(minimumValue) + (Int(tick) * nonZeroIncrement) if intValue != self.intValue { @@ -683,11 +701,14 @@ public class TGPDiscreteSlider:TGPSlider_INTERFACE_BUILDER { setNeedsDisplay() } - func pickTickFromSliderPosition(abscisse: CGFloat) -> UInt { + func pickTickFromSliderPosition(abscissa: CGFloat) -> UInt { let leftMost = trackRectangle.minX let rightMost = trackRectangle.maxX - let clampedAbscisse = max(leftMost, min(abscisse, rightMost)) - let ratio = Double(clampedAbscisse - leftMost) / Double(rightMost - leftMost) + let clampedAbscissa = max(leftMost, min(abscissa, rightMost)) + var ratio = Double(clampedAbscissa - leftMost) / Double(rightMost - leftMost) + ratio = (.rightToLeft == localeCharacterDirection) + ? 1.0 - ratio + : ratio let segments = max(1, tickCount - 1) return UInt(round( Double(segments) * ratio)) } diff --git a/TGPControlsDemo/TGPControlsDemo.xcodeproj/project.pbxproj b/TGPControlsDemo/TGPControlsDemo.xcodeproj/project.pbxproj index 8b6cd99..793e539 100644 --- a/TGPControlsDemo/TGPControlsDemo.xcodeproj/project.pbxproj +++ b/TGPControlsDemo/TGPControlsDemo.xcodeproj/project.pbxproj @@ -20,6 +20,10 @@ DC56BDCC1E46DEB900AAD0D9 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DC56BDCA1E46DEB900AAD0D9 /* Main.storyboard */; }; DC56BDCE1E46DEB900AAD0D9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DC56BDCD1E46DEB900AAD0D9 /* Assets.xcassets */; }; DC56BDD11E46DEB900AAD0D9 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DC56BDCF1E46DEB900AAD0D9 /* LaunchScreen.storyboard */; }; + DC7677B820C5C5BA006155F3 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = DC7677B620C5C5BA006155F3 /* Localizable.strings */; }; + DC7677B920C5C5BA006155F3 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = DC7677B620C5C5BA006155F3 /* Localizable.strings */; }; + DC7677BD20C5C712006155F3 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = DC7677BB20C5C712006155F3 /* InfoPlist.strings */; }; + DC7677BE20C5C712006155F3 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = DC7677BB20C5C712006155F3 /* InfoPlist.strings */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -50,6 +54,11 @@ DC56BDCD1E46DEB900AAD0D9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; DC56BDD01E46DEB900AAD0D9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; DC56BDD21E46DEB900AAD0D9 /* TGPControlsDemo-Pods-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "TGPControlsDemo-Pods-Info.plist"; sourceTree = ""; }; + DC7677B720C5C5BA006155F3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Localizable.strings; sourceTree = ""; }; + DC7677BA20C5C5E5006155F3 /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/Localizable.strings; sourceTree = ""; }; + DC7677BC20C5C712006155F3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/InfoPlist.strings; sourceTree = ""; }; + DC7677BF20C5C769006155F3 /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/InfoPlist.strings; sourceTree = ""; }; + DCEE05AD20C20D650081CD34 /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/Main.strings; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -119,6 +128,8 @@ DC56BDCF1E46DEB900AAD0D9 /* LaunchScreen.storyboard */, DC56BDD21E46DEB900AAD0D9 /* TGPControlsDemo-Pods-Info.plist */, DC4FF6511EA2E08C00BBF8E4 /* TGPControlsDemo-Cart-Info.plist */, + DC7677B620C5C5BA006155F3 /* Localizable.strings */, + DC7677BB20C5C712006155F3 /* InfoPlist.strings */, ); path = TGPControlsDemo; sourceTree = ""; @@ -188,6 +199,7 @@ knownRegions = ( en, Base, + ar, ); mainGroup = DC56BDBA1E46DEB900AAD0D9; productRefGroup = DC56BDC41E46DEB900AAD0D9 /* Products */; @@ -206,8 +218,10 @@ buildActionMask = 2147483647; files = ( DC4FF6481EA2E08C00BBF8E4 /* LaunchScreen.storyboard in Resources */, + DC7677B920C5C5BA006155F3 /* Localizable.strings in Resources */, DC4FF6491EA2E08C00BBF8E4 /* Assets.xcassets in Resources */, DC4FF64A1EA2E08C00BBF8E4 /* Main.storyboard in Resources */, + DC7677BE20C5C712006155F3 /* InfoPlist.strings in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -216,8 +230,10 @@ buildActionMask = 2147483647; files = ( DC56BDD11E46DEB900AAD0D9 /* LaunchScreen.storyboard in Resources */, + DC7677B820C5C5BA006155F3 /* Localizable.strings in Resources */, DC56BDCE1E46DEB900AAD0D9 /* Assets.xcassets in Resources */, DC56BDCC1E46DEB900AAD0D9 /* Main.storyboard in Resources */, + DC7677BD20C5C712006155F3 /* InfoPlist.strings in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -303,6 +319,7 @@ isa = PBXVariantGroup; children = ( DC56BDCB1E46DEB900AAD0D9 /* Base */, + DCEE05AD20C20D650081CD34 /* ar */, ); name = Main.storyboard; sourceTree = ""; @@ -315,6 +332,24 @@ name = LaunchScreen.storyboard; sourceTree = ""; }; + DC7677B620C5C5BA006155F3 /* Localizable.strings */ = { + isa = PBXVariantGroup; + children = ( + DC7677B720C5C5BA006155F3 /* Base */, + DC7677BA20C5C5E5006155F3 /* ar */, + ); + name = Localizable.strings; + sourceTree = ""; + }; + DC7677BB20C5C712006155F3 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + DC7677BC20C5C712006155F3 /* Base */, + DC7677BF20C5C769006155F3 /* ar */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ @@ -359,6 +394,7 @@ buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)"; ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -419,6 +455,7 @@ buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)"; ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; diff --git a/TGPControlsDemo/TGPControlsDemo/Base.lproj/InfoPlist.strings b/TGPControlsDemo/TGPControlsDemo/Base.lproj/InfoPlist.strings new file mode 100644 index 0000000..ff8561e --- /dev/null +++ b/TGPControlsDemo/TGPControlsDemo/Base.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +"CFBundleDisplayName" = "TGPControls"; +"NSHumanReadableCopyright" = "2016 Xavier Schott"; diff --git a/TGPControlsDemo/TGPControlsDemo/Base.lproj/Localizable.strings b/TGPControlsDemo/TGPControlsDemo/Base.lproj/Localizable.strings new file mode 100644 index 0000000..b56bbe6 --- /dev/null +++ b/TGPControlsDemo/TGPControlsDemo/Base.lproj/Localizable.strings @@ -0,0 +1,15 @@ +"oneTo10Labels.numbers" = "1 2 3 4 5 6 7 8 9 10"; +"alphabetLabels.letters" = "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z"; + +"pictureLabels.east" = "orient"; +"pictureLabels.west" = "occident"; +"pictureLabels.up" = "zénith"; +"pictureLabels.down" = "nadir"; +"pictureLabels.north" = "septentrion"; +"pictureLabels.south" = "midi"; + +"switch1Camel.off" = "OFF"; +"switch1Camel.on" = "ON"; + +"switch2Camel.off" = "O"; +"switch2Camel.on" = "l"; diff --git a/TGPControlsDemo/TGPControlsDemo/TGPControlsDemo-Cart-Info.plist b/TGPControlsDemo/TGPControlsDemo/TGPControlsDemo-Cart-Info.plist index ee3c849..482bce5 100644 --- a/TGPControlsDemo/TGPControlsDemo/TGPControlsDemo-Cart-Info.plist +++ b/TGPControlsDemo/TGPControlsDemo/TGPControlsDemo-Cart-Info.plist @@ -4,6 +4,8 @@ CFBundleDevelopmentRegion en + CFBundleDisplayName + TGPControls CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier @@ -15,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 4.0.0 + 5.0.3 CFBundleVersion 1 LSRequiresIPhoneOS diff --git a/TGPControlsDemo/TGPControlsDemo/TGPControlsDemo-Pods-Info.plist b/TGPControlsDemo/TGPControlsDemo/TGPControlsDemo-Pods-Info.plist index ee3c849..482bce5 100644 --- a/TGPControlsDemo/TGPControlsDemo/TGPControlsDemo-Pods-Info.plist +++ b/TGPControlsDemo/TGPControlsDemo/TGPControlsDemo-Pods-Info.plist @@ -4,6 +4,8 @@ CFBundleDevelopmentRegion en + CFBundleDisplayName + TGPControls CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier @@ -15,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 4.0.0 + 5.0.3 CFBundleVersion 1 LSRequiresIPhoneOS diff --git a/TGPControlsDemo/TGPControlsDemo/ViewController.swift b/TGPControlsDemo/TGPControlsDemo/ViewController.swift index 05000f2..357f419 100644 --- a/TGPControlsDemo/TGPControlsDemo/ViewController.swift +++ b/TGPControlsDemo/TGPControlsDemo/ViewController.swift @@ -18,14 +18,35 @@ class ViewController: UIViewController { @IBOutlet weak var dualColorSlider: TGPDiscreteSlider! @IBOutlet weak var stepper: UIStepper! + private func localizedStrings(_ key: String) -> [String] { + return NSLocalizedString(key, comment: "") + .split(separator: " ") + .map({ (substring) -> String in + return "\(substring)" + }) + } + override func viewDidLoad() { super.viewDidLoad() - alphabetLabels.names = ["A","B","C","D","E","F", "G","H","I","J","K","L","M", - "N","O","P","Q","R","S", "T","U","V","W","X","Y","Z"] - pictureLabels.names = ["orient", "occident", "zénith", "nadir", "septentrion", "midi"] - switch1Camel.names = ["OFF", "ON"] - switch2Camel.names = ["O", "l"] + oneTo10Labels.names = localizedStrings("oneTo10Labels.numbers") + + alphabetLabels.names = localizedStrings("alphabetLabels.letters") + alphabetSlider.tickCount = alphabetLabels.names.count // Number of letters in the given alphabet + + pictureLabels.names = [NSLocalizedString("pictureLabels.east", comment: ""), + NSLocalizedString("pictureLabels.west", comment: ""), + NSLocalizedString("pictureLabels.up", comment: ""), + NSLocalizedString("pictureLabels.down", comment: ""), + NSLocalizedString("pictureLabels.north", comment: ""), + NSLocalizedString("pictureLabels.south", comment: "")] + + switch1Camel.names = [NSLocalizedString("switch1Camel.off", comment: ""), + NSLocalizedString("switch1Camel.on", comment: "")] + + switch2Camel.names = [NSLocalizedString("switch2Camel.off", comment: ""), + NSLocalizedString("switch2Camel.on", comment: "")] + // Automatically track tick spacing changes and UIControlEventValueChanged alphabetSlider.ticksListener = alphabetLabels diff --git a/TGPControlsDemo/TGPControlsDemo/ar.lproj/InfoPlist.strings b/TGPControlsDemo/TGPControlsDemo/ar.lproj/InfoPlist.strings new file mode 100644 index 0000000..7118e6a --- /dev/null +++ b/TGPControlsDemo/TGPControlsDemo/ar.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +"CFBundleDisplayName" = "مراقبةTGP"; +"NSHumanReadableCopyright" = "2016 Xavier Schott"; diff --git a/TGPControlsDemo/TGPControlsDemo/ar.lproj/Localizable.strings b/TGPControlsDemo/TGPControlsDemo/ar.lproj/Localizable.strings new file mode 100644 index 0000000..b70d669 --- /dev/null +++ b/TGPControlsDemo/TGPControlsDemo/ar.lproj/Localizable.strings @@ -0,0 +1,15 @@ +"oneTo10Labels.numbers" = "١ ٢ ٣ ٤ ٥ ٦ ٧ ٨ ٩ ١٠"; +"alphabetLabels.letters" = "ا ب ج د ه و ز ح ط ي ك ل م ن س ع ف ص ق ر ش ت ث خ ذ ض ظ غ"; + +"pictureLabels.east" = "الشرق"; +"pictureLabels.west" = "غرب"; +"pictureLabels.up" = "إلى فوق"; +"pictureLabels.down" = "نزولا"; +"pictureLabels.north" = "شمال"; +"pictureLabels.south" = "جنوب"; + +"switch1Camel.off" = "اطفاء"; +"switch1Camel.on" = "تشغيل"; + +"switch2Camel.off" = "٠"; +"switch2Camel.on" = "١"; diff --git a/TGPControlsDemo/TGPControlsDemo/ar.lproj/Main.strings b/TGPControlsDemo/TGPControlsDemo/ar.lproj/Main.strings new file mode 100644 index 0000000..3e10a89 --- /dev/null +++ b/TGPControlsDemo/TGPControlsDemo/ar.lproj/Main.strings @@ -0,0 +1,15 @@ + +/* Class = "UILabel"; text = "Layers and transparency"; ObjectID = "1wG-kf-nie"; */ +"1wG-kf-nie.text" = "Layers and transparency"; + +/* Class = "UILabel"; text = "CamelLabels + Switch"; ObjectID = "A6t-OF-SSy"; */ +"A6t-OF-SSy.text" = "CamelLabels + Switch"; + +/* Class = "UILabel"; text = "Variations"; ObjectID = "XPd-Af-CYy"; */ +"XPd-Af-CYy.text" = "Variations"; + +/* Class = "UILabel"; text = "UIControlActions"; ObjectID = "gID-5d-KDe"; */ +"gID-5d-KDe.text" = "UIControlActions"; + +/* Class = "UILabel"; text = "DiscreteSlider + CamelLabels"; ObjectID = "hED-uQ-kcm"; */ +"hED-uQ-kcm.text" = "DiscreteSlider + CamelLabels";