TGPControls, custom awesome iOS controls
This commit is contained in:
commit
bb74b3820d
|
|
@ -0,0 +1,126 @@
|
|||
#
|
||||
# Be sure to run `pod spec lint TGPControls.podspec' to ensure this is a
|
||||
# valid spec and to remove all comments including this before submitting the spec.
|
||||
#
|
||||
# To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html
|
||||
# To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/
|
||||
#
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
|
||||
# ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
|
||||
#
|
||||
# These will help people to find your library, and whilst it
|
||||
# can feel like a chore to fill in it's definitely to your advantage. The
|
||||
# summary should be tweet-length, and the description more in depth.
|
||||
#
|
||||
|
||||
s.name = "TGPControls"
|
||||
s.version = "0.0.1"
|
||||
s.summary = "Custom Awesome iOS Controls."
|
||||
|
||||
s.description = <<-DESC
|
||||
Provide an iOS looking UISlider with discrete, controlable steps
|
||||
Provide dynamic, animated labels for discrete slider
|
||||
|
||||
DESC
|
||||
|
||||
s.homepage = "https://github.com/arquebuse/TGPControls"
|
||||
# s.screenshots = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif"
|
||||
|
||||
|
||||
# ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
|
||||
#
|
||||
# Licensing your code is important. See http://choosealicense.com for more info.
|
||||
# CocoaPods will detect a license file if there is a named LICENSE*
|
||||
# Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'.
|
||||
#
|
||||
|
||||
# s.license = "MIT (example)"
|
||||
s.license = { :type => "MIT", :file => "TGPControls_License.txt" }
|
||||
|
||||
|
||||
# ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
|
||||
#
|
||||
# Specify the authors of the library, with email addresses. Email addresses
|
||||
# of the authors are extracted from the SCM log. E.g. $ git log. CocoaPods also
|
||||
# accepts just a name if you'd rather not provide an email address.
|
||||
#
|
||||
# Specify a social_media_url where others can refer to, for example a twitter
|
||||
# profile URL.
|
||||
#
|
||||
|
||||
s.author = { "Arquebuse" => "xschott@gmail.com" }
|
||||
s.social_media_url = "http://twitter.com/xavierschott"
|
||||
|
||||
# ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
|
||||
#
|
||||
# If this Pod runs only on iOS or OS X, then specify the platform and
|
||||
# the deployment target. You can optionally include the target after the platform.
|
||||
#
|
||||
|
||||
s.platform = :ios, "7.0"
|
||||
|
||||
|
||||
# ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
|
||||
#
|
||||
# Specify the location from where the source should be retrieved.
|
||||
# Supports git, hg, bzr, svn and HTTP.
|
||||
#
|
||||
|
||||
s.source = { :git => "https://github.com/arquebuse/TGPControls.git", :tag => "0.0.1" }
|
||||
|
||||
|
||||
# ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
|
||||
#
|
||||
# CocoaPods is smart about how it includes source code. For source files
|
||||
# giving a folder will include any h, m, mm, c & cpp files. For header
|
||||
# files it will include any header in the folder.
|
||||
# Not including the public_header_files will make all headers public.
|
||||
#
|
||||
|
||||
s.source_files = "TGPControls", "TGPControls/**/*.{h,m}"
|
||||
# s.exclude_files = "TGPControls/**/*.{h,m}"
|
||||
|
||||
s.public_header_files = "TGPControls/**/*.{h}"
|
||||
|
||||
|
||||
# ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
|
||||
#
|
||||
# A list of resources included with the Pod. These are copied into the
|
||||
# target bundle with a build phase script. Anything else will be cleaned.
|
||||
# You can preserve files from being cleaned, please don't preserve
|
||||
# non-essential files like tests, examples and documentation.
|
||||
#
|
||||
|
||||
# s.resource = "TGPImages.car"
|
||||
# s.resources = "TGPImages.xcassets/*.imageset"
|
||||
|
||||
# s.preserve_paths = "FilesToSave", "MoreFilesToSave"
|
||||
|
||||
|
||||
# ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
|
||||
#
|
||||
# Link your library with frameworks, or libraries. Libraries do not include
|
||||
# the lib prefix of their name.
|
||||
#
|
||||
|
||||
# s.framework = "SomeFramework"
|
||||
# s.frameworks = "SomeFramework", "AnotherFramework"
|
||||
|
||||
# s.library = "iconv"
|
||||
# s.libraries = "iconv", "xml2"
|
||||
|
||||
|
||||
# ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
|
||||
#
|
||||
# If your library depends on compiler flags you can set them in the xcconfig hash
|
||||
# where they will only apply to your library. If you depend on other Podspecs
|
||||
# you can include multiple dependencies to ensure it works.
|
||||
|
||||
s.requires_arc = true
|
||||
|
||||
# s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" }
|
||||
# s.dependency "JSONKit", "~> 1.4"
|
||||
|
||||
end
|
||||
|
|
@ -0,0 +1,395 @@
|
|||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
DC0468E31A75962E0084DE3E /* TGPCamelLabels7.m in Sources */ = {isa = PBXBuildFile; fileRef = DC0468E01A75962E0084DE3E /* TGPCamelLabels7.m */; };
|
||||
DC0468E41A75962E0084DE3E /* TGPDiscreteSlider7.m in Sources */ = {isa = PBXBuildFile; fileRef = DC0468E21A75962E0084DE3E /* TGPDiscreteSlider7.m */; };
|
||||
DC0468E71A7596690084DE3E /* TGPCamelLabels.m in Sources */ = {isa = PBXBuildFile; fileRef = DC0468E61A7596690084DE3E /* TGPCamelLabels.m */; };
|
||||
DC0468EA1A7596930084DE3E /* TGPDiscreteSlider.m in Sources */ = {isa = PBXBuildFile; fileRef = DC0468E91A7596930084DE3E /* TGPDiscreteSlider.m */; };
|
||||
DC101D661A75749600ECCF80 /* libTGPControls.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC101D5A1A75749600ECCF80 /* libTGPControls.a */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
DC101D671A75749600ECCF80 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = DC101D521A75749600ECCF80 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = DC101D591A75749600ECCF80;
|
||||
remoteInfo = TGPControls;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
DC101D581A75749600ECCF80 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "include/$(PRODUCT_NAME)";
|
||||
dstSubfolderSpec = 16;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
DC0468DF1A75962E0084DE3E /* TGPCamelLabels7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TGPCamelLabels7.h; sourceTree = "<group>"; };
|
||||
DC0468E01A75962E0084DE3E /* TGPCamelLabels7.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TGPCamelLabels7.m; sourceTree = "<group>"; };
|
||||
DC0468E11A75962E0084DE3E /* TGPDiscreteSlider7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TGPDiscreteSlider7.h; sourceTree = "<group>"; };
|
||||
DC0468E21A75962E0084DE3E /* TGPDiscreteSlider7.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TGPDiscreteSlider7.m; sourceTree = "<group>"; };
|
||||
DC0468E51A7596690084DE3E /* TGPCamelLabels.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TGPCamelLabels.h; sourceTree = "<group>"; };
|
||||
DC0468E61A7596690084DE3E /* TGPCamelLabels.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TGPCamelLabels.m; sourceTree = "<group>"; };
|
||||
DC0468E81A7596930084DE3E /* TGPDiscreteSlider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TGPDiscreteSlider.h; sourceTree = "<group>"; };
|
||||
DC0468E91A7596930084DE3E /* TGPDiscreteSlider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TGPDiscreteSlider.m; sourceTree = "<group>"; };
|
||||
DC101D5A1A75749600ECCF80 /* libTGPControls.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libTGPControls.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DC101D651A75749600ECCF80 /* TGPControlsTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TGPControlsTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DC101D6B1A75749600ECCF80 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
DC101D7A1A75756300ECCF80 /* TGPControls_License.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = TGPControls_License.txt; sourceTree = "<group>"; };
|
||||
DC101D7B1A75756300ECCF80 /* TGPControls.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; path = TGPControls.podspec; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
DC101D571A75749600ECCF80 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
DC101D621A75749600ECCF80 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
DC101D661A75749600ECCF80 /* libTGPControls.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
DC0468DE1A75962E0084DE3E /* TGPControls */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DC0468E51A7596690084DE3E /* TGPCamelLabels.h */,
|
||||
DC0468E61A7596690084DE3E /* TGPCamelLabels.m */,
|
||||
DC0468E81A7596930084DE3E /* TGPDiscreteSlider.h */,
|
||||
DC0468E91A7596930084DE3E /* TGPDiscreteSlider.m */,
|
||||
DC0468DF1A75962E0084DE3E /* TGPCamelLabels7.h */,
|
||||
DC0468E01A75962E0084DE3E /* TGPCamelLabels7.m */,
|
||||
DC0468E11A75962E0084DE3E /* TGPDiscreteSlider7.h */,
|
||||
DC0468E21A75962E0084DE3E /* TGPDiscreteSlider7.m */,
|
||||
);
|
||||
path = TGPControls;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DC101D511A75749600ECCF80 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DC101D7A1A75756300ECCF80 /* TGPControls_License.txt */,
|
||||
DC101D7B1A75756300ECCF80 /* TGPControls.podspec */,
|
||||
DC0468DE1A75962E0084DE3E /* TGPControls */,
|
||||
DC101D691A75749600ECCF80 /* TGPControlsTests */,
|
||||
DC101D5B1A75749600ECCF80 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DC101D5B1A75749600ECCF80 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DC101D5A1A75749600ECCF80 /* libTGPControls.a */,
|
||||
DC101D651A75749600ECCF80 /* TGPControlsTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DC101D691A75749600ECCF80 /* TGPControlsTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DC101D6A1A75749600ECCF80 /* Supporting Files */,
|
||||
);
|
||||
path = TGPControlsTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DC101D6A1A75749600ECCF80 /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DC101D6B1A75749600ECCF80 /* Info.plist */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
DC101D591A75749600ECCF80 /* TGPControls */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = DC101D6E1A75749600ECCF80 /* Build configuration list for PBXNativeTarget "TGPControls" */;
|
||||
buildPhases = (
|
||||
DC101D561A75749600ECCF80 /* Sources */,
|
||||
DC101D571A75749600ECCF80 /* Frameworks */,
|
||||
DC101D581A75749600ECCF80 /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = TGPControls;
|
||||
productName = TGPControls;
|
||||
productReference = DC101D5A1A75749600ECCF80 /* libTGPControls.a */;
|
||||
productType = "com.apple.product-type.library.static";
|
||||
};
|
||||
DC101D641A75749600ECCF80 /* TGPControlsTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = DC101D711A75749600ECCF80 /* Build configuration list for PBXNativeTarget "TGPControlsTests" */;
|
||||
buildPhases = (
|
||||
DC101D611A75749600ECCF80 /* Sources */,
|
||||
DC101D621A75749600ECCF80 /* Frameworks */,
|
||||
DC101D631A75749600ECCF80 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
DC101D681A75749600ECCF80 /* PBXTargetDependency */,
|
||||
);
|
||||
name = TGPControlsTests;
|
||||
productName = TGPControlsTests;
|
||||
productReference = DC101D651A75749600ECCF80 /* TGPControlsTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
DC101D521A75749600ECCF80 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0610;
|
||||
ORGANIZATIONNAME = arquebuse;
|
||||
TargetAttributes = {
|
||||
DC101D591A75749600ECCF80 = {
|
||||
CreatedOnToolsVersion = 6.1.1;
|
||||
};
|
||||
DC101D641A75749600ECCF80 = {
|
||||
CreatedOnToolsVersion = 6.1.1;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = DC101D551A75749600ECCF80 /* Build configuration list for PBXProject "TGPControls" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = DC101D511A75749600ECCF80;
|
||||
productRefGroup = DC101D5B1A75749600ECCF80 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
DC101D591A75749600ECCF80 /* TGPControls */,
|
||||
DC101D641A75749600ECCF80 /* TGPControlsTests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
DC101D631A75749600ECCF80 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
DC101D561A75749600ECCF80 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
DC0468E31A75962E0084DE3E /* TGPCamelLabels7.m in Sources */,
|
||||
DC0468E71A7596690084DE3E /* TGPCamelLabels.m in Sources */,
|
||||
DC0468E41A75962E0084DE3E /* TGPDiscreteSlider7.m in Sources */,
|
||||
DC0468EA1A7596930084DE3E /* TGPDiscreteSlider.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
DC101D611A75749600ECCF80 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
DC101D681A75749600ECCF80 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = DC101D591A75749600ECCF80 /* TGPControls */;
|
||||
targetProxy = DC101D671A75749600ECCF80 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
DC101D6C1A75749600ECCF80 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
DC101D6D1A75749600ECCF80 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
DC101D6F1A75749600ECCF80 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
DC101D701A75749600ECCF80 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
DC101D721A75749600ECCF80 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
INFOPLIST_FILE = TGPControlsTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
DC101D731A75749600ECCF80 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
);
|
||||
INFOPLIST_FILE = TGPControlsTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
DC101D551A75749600ECCF80 /* Build configuration list for PBXProject "TGPControls" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
DC101D6C1A75749600ECCF80 /* Debug */,
|
||||
DC101D6D1A75749600ECCF80 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
DC101D6E1A75749600ECCF80 /* Build configuration list for PBXNativeTarget "TGPControls" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
DC101D6F1A75749600ECCF80 /* Debug */,
|
||||
DC101D701A75749600ECCF80 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
DC101D711A75749600ECCF80 /* Build configuration list for PBXNativeTarget "TGPControlsTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
DC101D721A75749600ECCF80 /* Debug */,
|
||||
DC101D731A75749600ECCF80 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = DC101D521A75749600ECCF80 /* Project object */;
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:TGPControls.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
// @file: TGPCamelLabels.h
|
||||
// @project: TGPControls
|
||||
//
|
||||
// @history: Created November 27, 2014 (Thanksgiving Day)
|
||||
// @author: Xavier Schott
|
||||
// mailto://xschott@gmail.com
|
||||
// http://thegothicparty.com
|
||||
// tel://+18089383634
|
||||
//
|
||||
// @license: http://opensource.org/licenses/MIT
|
||||
// Copyright (c) 2014, 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 "TGPCamelLabels7.h"
|
||||
|
||||
IB_DESIGNABLE
|
||||
@interface TGPCamelLabels : TGPCamelLabels7
|
||||
|
||||
@property (nonatomic) IBInspectable NSUInteger tickCount; // Only used if [labels count] < 1
|
||||
@property (nonatomic) IBInspectable CGFloat ticksDistance;
|
||||
@property (nonatomic) IBInspectable NSUInteger value;
|
||||
|
||||
@property (nonatomic) IBInspectable NSString * upFontName;
|
||||
@property (nonatomic) IBInspectable CGFloat upFontSize;
|
||||
@property (nonatomic) IBInspectable UIColor * upFontColor;
|
||||
|
||||
@property (nonatomic) IBInspectable NSString * downFontName;
|
||||
@property (nonatomic) IBInspectable CGFloat downFontSize;
|
||||
@property (nonatomic) IBInspectable UIColor * downFontColor;
|
||||
|
||||
@end
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
// @file: TGPCamelLabels.m
|
||||
// @project: TGPControls
|
||||
//
|
||||
// @history: Created November 27, 2014 (Thanksgiving Day)
|
||||
// @author: Xavier Schott
|
||||
// mailto://xschott@gmail.com
|
||||
// http://thegothicparty.com
|
||||
// tel://+18089383634
|
||||
//
|
||||
// @license: http://opensource.org/licenses/MIT
|
||||
// Copyright (c) 2014, 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 "TGPCamelLabels.h"
|
||||
|
||||
@implementation TGPCamelLabels
|
||||
|
||||
@end
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
// @file: TGPCamelLabels7.h
|
||||
// @project: TGPControls
|
||||
//
|
||||
// @history: Created July 4th, 2014 (Independence Day)
|
||||
// @author: Xavier Schott
|
||||
// mailto://xschott@gmail.com
|
||||
// http://thegothicparty.com
|
||||
// tel://+18089383634
|
||||
//
|
||||
// @license: http://opensource.org/licenses/MIT
|
||||
// Copyright (c) 2014, 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/UIKit.h>
|
||||
|
||||
@interface TGPCamelLabels7 : UIControl
|
||||
|
||||
@property (nonatomic) NSUInteger tickCount; // Only used if [labels count] < 1
|
||||
@property (nonatomic) CGFloat ticksDistance;
|
||||
@property (nonatomic) NSUInteger value;
|
||||
|
||||
@property (nonatomic) NSString * upFontName;
|
||||
@property (nonatomic) CGFloat upFontSize;
|
||||
@property (nonatomic) UIColor * upFontColor;
|
||||
|
||||
@property (nonatomic) NSString * downFontName;
|
||||
@property (nonatomic) CGFloat downFontSize;
|
||||
@property (nonatomic) UIColor * downFontColor;
|
||||
|
||||
@property (nonatomic) NSArray * names; // Will dictate the number of ticks
|
||||
|
||||
@end
|
||||
|
|
@ -0,0 +1,285 @@
|
|||
// @file: TGPCamelLabels7.m
|
||||
// @project: TGPControls
|
||||
//
|
||||
// @history: Created July 4th, 2014 (Independence Day)
|
||||
// @author: Xavier Schott
|
||||
// mailto://xschott@gmail.com
|
||||
// http://thegothicparty.com
|
||||
// tel://+18089383634
|
||||
//
|
||||
// @license: http://opensource.org/licenses/MIT
|
||||
// Copyright (c) 2014, 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 "TGPCamelLabels7.h"
|
||||
|
||||
@interface TGPCamelLabels7()
|
||||
@property (nonatomic, assign) NSUInteger lastValue;
|
||||
@property (nonatomic, retain) NSMutableArray * upLabels;
|
||||
@property (nonatomic, retain) NSMutableArray * dnLabels;
|
||||
@end
|
||||
|
||||
@implementation TGPCamelLabels7
|
||||
|
||||
#pragma mark properties
|
||||
|
||||
- (void)setTickCount:(NSUInteger)tickCount {
|
||||
// calculated property
|
||||
// Put some order to tickCount: 1 >= count >= 128
|
||||
const unsigned int count = (unsigned int) MAX(1, MIN(tickCount, 128));
|
||||
[self debugNames:count];
|
||||
[self layoutTrack];
|
||||
}
|
||||
|
||||
- (NSUInteger)tickCount {
|
||||
// Dynamic property
|
||||
return [_names count];
|
||||
}
|
||||
|
||||
- (void)setTicksDistance:(CGFloat)ticksDistance {
|
||||
_ticksDistance = MAX(0, ticksDistance);
|
||||
[self layoutTrack];
|
||||
}
|
||||
|
||||
- (void)setValue:(NSUInteger)value {
|
||||
_value = value;
|
||||
[self dockEffect:.15];
|
||||
}
|
||||
|
||||
- (void)setUpFontName:(NSString *)upFontName {
|
||||
_upFontName = upFontName;
|
||||
[self layoutTrack];
|
||||
}
|
||||
|
||||
- (void)setUpFontSize:(CGFloat)upFontSize {
|
||||
_upFontSize = upFontSize;
|
||||
[self layoutTrack];
|
||||
}
|
||||
|
||||
- (void)setUpFontColor:(UIColor *)upFontColor {
|
||||
_upFontColor = upFontColor;
|
||||
[self layoutTrack];
|
||||
}
|
||||
|
||||
- (void)setDownFontName:(NSString *)downFontName {
|
||||
_downFontName = downFontName;
|
||||
[self layoutTrack];
|
||||
}
|
||||
|
||||
- (void)setDownFontSize:(CGFloat)downFontSize {
|
||||
_downFontSize = downFontSize;
|
||||
[self layoutTrack];
|
||||
}
|
||||
|
||||
- (void)setDownFontColor:(UIColor *)downFontColor {
|
||||
_downFontColor = downFontColor;
|
||||
[self layoutTrack];
|
||||
}
|
||||
|
||||
// NSArray<NSString*>
|
||||
- (void)setNames:(NSArray *)names {
|
||||
NSAssert(names.count > 0, @"names.count");
|
||||
_names = names;
|
||||
[self layoutTrack];
|
||||
}
|
||||
|
||||
#pragma mark UIView
|
||||
|
||||
- (id)initWithCoder:(NSCoder *)aDecoder {
|
||||
self = [super initWithCoder:aDecoder];
|
||||
if(self != nil) {
|
||||
[self initProperties];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
self = [super initWithFrame:frame];
|
||||
if(self != nil) {
|
||||
[self initProperties];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
// clickthrough
|
||||
-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
|
||||
for (UIView *view in self.subviews) {
|
||||
if (!view.hidden && view.alpha > 0 && view.userInteractionEnabled && [view pointInside:[self convertPoint:point toView:view] withEvent:event])
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
#pragma mark TGPCamelSlider
|
||||
|
||||
- (void)initProperties {
|
||||
_ticksDistance = 44.0;
|
||||
_value = 0;
|
||||
[self debugNames:10];
|
||||
|
||||
_upFontName = nil;
|
||||
_upFontSize = 12;
|
||||
_upFontColor = nil;
|
||||
|
||||
_downFontName = nil;
|
||||
_downFontSize = 12;
|
||||
_downFontColor = nil;
|
||||
|
||||
_upLabels = [NSMutableArray array];
|
||||
_dnLabels = [NSMutableArray array];
|
||||
|
||||
_lastValue = NSNotFound; // Never tapped
|
||||
[self layoutTrack];
|
||||
}
|
||||
|
||||
- (void)debugNames:(unsigned int)count {
|
||||
// Dynamic property, will create an array with labels, generally for debugging purposes
|
||||
const NSMutableArray * array = [NSMutableArray array];
|
||||
for(int iterate = 1; iterate <= count; iterate++) {
|
||||
[array addObject:[NSString stringWithFormat:@"%d", iterate ]];
|
||||
}
|
||||
[self setNames:(NSArray *) array];
|
||||
}
|
||||
|
||||
- (void)layoutTrack {
|
||||
[self.upLabels enumerateObjectsUsingBlock:^(UIView * view, NSUInteger idx, BOOL *stop) {
|
||||
[view removeFromSuperview];
|
||||
}];
|
||||
[self.upLabels removeAllObjects];
|
||||
[self.dnLabels enumerateObjectsUsingBlock:^(UIView * view, NSUInteger idx, BOOL *stop) {
|
||||
[view removeFromSuperview];
|
||||
}];
|
||||
[self.dnLabels removeAllObjects];
|
||||
|
||||
const NSUInteger count = self.names.count;
|
||||
if( count > 0) {
|
||||
CGFloat centerX = (self.bounds.size.width - ((count - 1) * self.ticksDistance))/2.0;
|
||||
const CGFloat centerY = self.bounds.size.height / 2.0;
|
||||
for(NSString * name in self.names) {
|
||||
UILabel * upLabel = [[UILabel alloc] initWithFrame:CGRectZero];
|
||||
[self.upLabels addObject:upLabel];
|
||||
upLabel.text = name;
|
||||
upLabel.font = ((self.upFontName != nil)
|
||||
? [UIFont fontWithName:self.upFontName size:self.upFontSize]
|
||||
: [UIFont boldSystemFontOfSize:self.upFontSize]);
|
||||
upLabel.textColor = ((self.upFontColor != nil)
|
||||
? self.upFontColor
|
||||
: self.tintColor);
|
||||
[upLabel sizeToFit];
|
||||
upLabel.center = CGPointMake(centerX, centerY);
|
||||
upLabel.frame = ({
|
||||
CGRect frame = upLabel.frame;
|
||||
// frame.origin.y = 0;
|
||||
frame.origin.y = self.bounds.size.height - frame.size.height;
|
||||
frame;
|
||||
});
|
||||
upLabel.alpha = 0.0;
|
||||
[self addSubview:upLabel];
|
||||
|
||||
UILabel * dnLabel = [[UILabel alloc] initWithFrame:CGRectZero];
|
||||
[self.dnLabels addObject:dnLabel];
|
||||
dnLabel.text = name;
|
||||
dnLabel.font = ((self.downFontName != nil)
|
||||
? [UIFont fontWithName:self.downFontName size:self.downFontSize]
|
||||
: [UIFont boldSystemFontOfSize:self.downFontSize]);
|
||||
dnLabel.textColor = ((self.downFontColor != nil)
|
||||
? self.downFontColor
|
||||
: [UIColor grayColor]);
|
||||
[dnLabel sizeToFit];
|
||||
dnLabel.center = CGPointMake(centerX, centerY);
|
||||
dnLabel.frame = ({
|
||||
CGRect frame = dnLabel.frame;
|
||||
frame.origin.y = self.bounds.size.height - frame.size.height;
|
||||
frame;
|
||||
});
|
||||
[self addSubview:dnLabel];
|
||||
|
||||
centerX += self.ticksDistance;
|
||||
}
|
||||
[self dockEffect:0.0];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dockEffect:(NSTimeInterval)duration
|
||||
{
|
||||
const NSUInteger up = self.value;
|
||||
|
||||
// Unlike the National Parks from which it is inspired, this Dock Effect
|
||||
// does not abruptly change from BOLD to plain. Instead, we have 2 sets of
|
||||
// labels, which are faded back and forth, in unisson.
|
||||
// - BOLD to plain
|
||||
// - Black to gray
|
||||
// - high to low
|
||||
// Each animation picks up where the previous left off
|
||||
void (^moveBlock)() = ^void() {
|
||||
// Bring almost all down
|
||||
[self.upLabels enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
|
||||
if( up != idx) {
|
||||
[self moveDown:obj withAlpha:0.f];
|
||||
}
|
||||
}];
|
||||
[self.dnLabels enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
|
||||
if( up != idx) {
|
||||
[self moveDown:obj withAlpha:1.f];
|
||||
}
|
||||
}];
|
||||
|
||||
// Bring the selection up
|
||||
if(up < [self.upLabels count]) {
|
||||
[self moveUp:[self.upLabels objectAtIndex:up] withAlpha:1.f];
|
||||
}
|
||||
if(up < [self.dnLabels count]) {
|
||||
[self moveUp:[self.dnLabels objectAtIndex:up] withAlpha:0.f];
|
||||
}
|
||||
};
|
||||
|
||||
if(duration > 0) {
|
||||
[UIView animateWithDuration:duration
|
||||
delay:0
|
||||
options:(UIViewAnimationOptionBeginFromCurrentState +
|
||||
UIViewAnimationOptionCurveLinear)
|
||||
animations:moveBlock
|
||||
completion:nil];
|
||||
} else {
|
||||
moveBlock();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)moveDown:(UIView*)aView withAlpha:(CGFloat) alpha
|
||||
{
|
||||
aView.frame = ({
|
||||
CGRect frame = aView.frame;
|
||||
frame.origin.y = self.bounds.size.height - frame.size.height;
|
||||
frame;
|
||||
});
|
||||
[aView setAlpha:alpha];
|
||||
}
|
||||
|
||||
- (void)moveUp:(UIView*)aView withAlpha:(CGFloat) alpha
|
||||
{
|
||||
aView.frame = ({
|
||||
CGRect frame = aView.frame;
|
||||
frame.origin.y = 0;
|
||||
frame;
|
||||
});
|
||||
[aView setAlpha:alpha];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
// @file: TGPDiscreteSlider.h
|
||||
// @project: TGPControls
|
||||
//
|
||||
// @history: Created November 27, 2014 (Thanksgiving Day)
|
||||
// @author: Xavier Schott
|
||||
// mailto://xschott@gmail.com
|
||||
// http://thegothicparty.com
|
||||
// tel://+18089383634
|
||||
//
|
||||
// @license: http://opensource.org/licenses/MIT
|
||||
// Copyright (c) 2014, 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 "TGPDiscreteSlider7.h"
|
||||
|
||||
IB_DESIGNABLE
|
||||
@interface TGPDiscreteSlider : TGPDiscreteSlider7
|
||||
|
||||
@property (nonatomic) IBInspectable int tickStyle;
|
||||
@property (nonatomic) IBInspectable CGSize tickSize;
|
||||
@property (nonatomic) IBInspectable int tickCount;
|
||||
|
||||
@property (nonatomic) IBInspectable int trackStyle;
|
||||
@property (nonatomic) IBInspectable CGFloat trackThickness;
|
||||
|
||||
@property (nonatomic) IBInspectable int thumbStyle;
|
||||
@property (nonatomic) IBInspectable CGSize thumbSize;
|
||||
@property (nonatomic) IBInspectable UIColor * thumbColor;
|
||||
@property (nonatomic) IBInspectable CGFloat thumbSRadius;
|
||||
@property (nonatomic) IBInspectable CGSize thumbSOffset;
|
||||
|
||||
// AKA: UISlider value (as CGFloat for compatibility with UISlider API, but expected to contain integers)
|
||||
@property (nonatomic) IBInspectable CGFloat minimumValue;
|
||||
@property (nonatomic) IBInspectable CGFloat value;
|
||||
|
||||
@property (nonatomic) IBInspectable int incrementValue;
|
||||
|
||||
@end
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
// @file: TGPDiscreteSlider.m
|
||||
// @project: TGPControls
|
||||
//
|
||||
// @history: Created November 27, 2014 (Thanksgiving Day)
|
||||
// @author: Xavier Schott
|
||||
// mailto://xschott@gmail.com
|
||||
// http://thegothicparty.com
|
||||
// tel://+18089383634
|
||||
//
|
||||
// @license: http://opensource.org/licenses/MIT
|
||||
// Copyright (c) 2014, 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 "TGPDiscreteSlider.h"
|
||||
|
||||
@implementation TGPDiscreteSlider
|
||||
|
||||
#pragma mark properties
|
||||
|
||||
- (void)setThumbSRadius:(CGFloat)thumbSRadius {
|
||||
// adapter
|
||||
self.thumbShadowRadius = thumbSRadius;
|
||||
}
|
||||
|
||||
- (void)setThumbSOffset:(CGSize)thumbSOffset {
|
||||
// adapter
|
||||
self.thumbShadowOffset = thumbSOffset;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
// @file: TGPDiscreteSlider7.h
|
||||
// @project: TGPControls
|
||||
//
|
||||
// @history: Created July 4th, 2014 (Independence Day)
|
||||
// @author: Xavier Schott
|
||||
// mailto://xschott@gmail.com
|
||||
// http://thegothicparty.com
|
||||
// tel://+18089383634
|
||||
//
|
||||
// @license: http://opensource.org/licenses/MIT
|
||||
// Copyright (c) 2014, 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/UIKit.h>
|
||||
|
||||
@interface TGPDiscreteSlider7 :
|
||||
|
||||
// Interface builder hides the IBInspectable for UIControl
|
||||
#if TARGET_INTERFACE_BUILDER
|
||||
UIView
|
||||
#else // !TARGET_INTERFACE_BUILDER
|
||||
UIControl
|
||||
#endif // TARGET_INTERFACE_BUILDER
|
||||
|
||||
typedef NS_ENUM(int, ComponentStyle) {
|
||||
ComponentStyleIOS = 0,
|
||||
ComponentStyleRectangular,
|
||||
ComponentStyleRounded,
|
||||
ComponentStyleInvisible,
|
||||
ComponentStyleImage
|
||||
};
|
||||
|
||||
@property (nonatomic) ComponentStyle tickStyle;
|
||||
@property (nonatomic) CGSize tickSize;
|
||||
@property (nonatomic) int tickCount;
|
||||
@property (nonatomic, readonly) CGFloat ticksDistance;
|
||||
|
||||
@property (nonatomic) ComponentStyle trackStyle;
|
||||
@property (nonatomic) CGFloat trackThickness;
|
||||
|
||||
@property (nonatomic) ComponentStyle thumbStyle;
|
||||
@property (nonatomic) CGSize thumbSize;
|
||||
@property (nonatomic) UIColor * thumbColor;
|
||||
@property (nonatomic) CGFloat thumbShadowRadius;
|
||||
@property (nonatomic) CGSize thumbShadowOffset;
|
||||
|
||||
// AKA: UISlider value (as CGFloat for compatibility with UISlider API, but expected to contain integers)
|
||||
@property (nonatomic) CGFloat minimumValue;
|
||||
@property (nonatomic) CGFloat value;
|
||||
|
||||
@property (nonatomic) int incrementValue;
|
||||
|
||||
@end
|
||||
|
|
@ -0,0 +1,486 @@
|
|||
// @file: TGPDiscreteSlider7.m
|
||||
// @project: TGPControls
|
||||
//
|
||||
// @history: Created July 4th, 2014 (Independence Day)
|
||||
// @author: Xavier Schott
|
||||
// mailto://xschott@gmail.com
|
||||
// http://thegothicparty.com
|
||||
// tel://+18089383634
|
||||
//
|
||||
// @license: http://opensource.org/licenses/MIT
|
||||
// Copyright (c) 2014, 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 "TGPDiscreteSlider7.h"
|
||||
|
||||
static CGFloat iOSThumbShadowRadius = 4.0;
|
||||
static CGSize iosThumbShadowOffset = (CGSize){0, 3};
|
||||
|
||||
@interface TGPDiscreteSlider7 () {
|
||||
int _intValue;
|
||||
int _intMinimumValue;
|
||||
}
|
||||
@property (nonatomic) NSMutableArray * ticksAbscisses;
|
||||
@property (nonatomic, assign) CGFloat thumbAbscisse;
|
||||
@property (nonatomic) CALayer * thumbLayer;
|
||||
@property (nonatomic) CALayer * colorTrackLayer;
|
||||
@property (nonatomic) CGRect trackRectangle;
|
||||
@end
|
||||
|
||||
@implementation TGPDiscreteSlider7
|
||||
|
||||
#pragma mark properties
|
||||
|
||||
- (void)setTickStyle:(ComponentStyle)tickStyle {
|
||||
_tickStyle = tickStyle;
|
||||
[self layoutTrack];
|
||||
}
|
||||
|
||||
- (void)setTickSize:(CGSize)tickSize {
|
||||
_tickSize.width = MAX(0, tickSize.width);
|
||||
_tickSize.height = MAX(0, tickSize.height);
|
||||
[self layoutTrack];
|
||||
}
|
||||
|
||||
- (void)setTickCount:(int)tickCount {
|
||||
_tickCount = MAX(2, tickCount);
|
||||
[self layoutTrack];
|
||||
}
|
||||
|
||||
- (CGFloat)ticksDistance {
|
||||
NSAssert1(self.tickCount > 1, @"2 ticks minimum %d", self.tickCount);
|
||||
const unsigned int segments = MAX(1, self.tickCount - 1);
|
||||
const CGFloat thumbWidth = [self thumbSizeIncludingShadow].width;
|
||||
const double trackLength = (double)(self.frame.size.width - thumbWidth);
|
||||
|
||||
return (CGFloat) (trackLength / segments);
|
||||
}
|
||||
|
||||
- (void)setTrackStyle:(ComponentStyle)trackStyle {
|
||||
_trackStyle = trackStyle;
|
||||
[self layoutTrack];
|
||||
}
|
||||
|
||||
- (void)setTrackThickness:(CGFloat)trackThickness {
|
||||
_trackThickness = MAX(0, trackThickness);
|
||||
[self layoutTrack];
|
||||
}
|
||||
|
||||
- (void)setThumbStyle:(ComponentStyle)thumbStyle {
|
||||
_thumbStyle = thumbStyle;
|
||||
[self layoutTrack];
|
||||
}
|
||||
|
||||
- (void)setThumbSize:(CGSize)thumbSize {
|
||||
_thumbSize.width = MAX(1, thumbSize.width);
|
||||
_thumbSize.height = MAX(1, thumbSize.height);
|
||||
[self layoutTrack];
|
||||
}
|
||||
|
||||
- (void)setThumbShadowRadius:(CGFloat)thumbShadowRadius {
|
||||
_thumbShadowRadius = thumbShadowRadius;
|
||||
[self layoutTrack];
|
||||
}
|
||||
|
||||
- (void)setIncrementValue:(int)incrementValue {
|
||||
_incrementValue = incrementValue;
|
||||
if(0 == incrementValue) {
|
||||
_incrementValue = 1; // nonZeroIncrement
|
||||
}
|
||||
[self layoutTrack];
|
||||
}
|
||||
|
||||
// AKA: UISlider value (as CGFloat for compatibility with UISlider API, but expected to contain integers)
|
||||
- (void)setMinimumValue:(CGFloat)minimumValue {
|
||||
_intMinimumValue = minimumValue;
|
||||
[self layoutTrack];
|
||||
}
|
||||
|
||||
- (CGFloat)minimumValue {
|
||||
return _intMinimumValue; // calculated property, with a float-to-int adapter
|
||||
}
|
||||
|
||||
- (void)setValue:(CGFloat)value {
|
||||
const unsigned int nonZeroIncrement = ((0 == _incrementValue) ? 1 : _incrementValue);
|
||||
const int rootValue = ((value - self.minimumValue) / nonZeroIncrement);
|
||||
_intValue = self.minimumValue + (rootValue * nonZeroIncrement);
|
||||
[self layoutTrack];
|
||||
}
|
||||
|
||||
- (CGFloat)value {
|
||||
return _intValue; // calculated property, with a float-to-int adapter
|
||||
}
|
||||
|
||||
#pragma mark UIControl
|
||||
|
||||
- (id)initWithCoder:(NSCoder *)aDecoder {
|
||||
self = [super initWithCoder:aDecoder];
|
||||
if(self != nil) {
|
||||
[self initProperties];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
self = [super initWithFrame:frame];
|
||||
if(self != nil) {
|
||||
[self initProperties];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)drawRect:(CGRect)rect {
|
||||
[self drawTrack];
|
||||
[self drawThumb];
|
||||
}
|
||||
|
||||
#pragma mark TGPDiscreteSlider7
|
||||
|
||||
- (void)initProperties {
|
||||
_tickStyle = ComponentStyleRectangular;
|
||||
_tickSize = (CGSize) {1.0, 4.0};
|
||||
_tickCount = 11;
|
||||
_trackStyle = ComponentStyleIOS;
|
||||
_trackThickness = 2.0;
|
||||
_thumbStyle = ComponentStyleIOS;
|
||||
_thumbSize = (CGSize) {10.0, 10.0};
|
||||
_thumbColor = [UIColor lightGrayColor];
|
||||
_thumbShadowRadius = 0.0;
|
||||
_thumbShadowOffset = CGSizeZero;
|
||||
_intMinimumValue = -5;
|
||||
_incrementValue = 1;
|
||||
_intValue = 0;
|
||||
_ticksAbscisses = [NSMutableArray array];
|
||||
_thumbAbscisse = 0.0;
|
||||
_trackRectangle = CGRectZero;
|
||||
|
||||
// In case we need a colored track, initialize it now
|
||||
// There may be a more elegant way to do this than with a CALayer,
|
||||
// but then again CALayer brings free animation and will animate along the thumb
|
||||
_colorTrackLayer = [CALayer layer];
|
||||
_colorTrackLayer.backgroundColor = [[UIColor colorWithHue:211.0/360.0 saturation:1 brightness:1 alpha:1] CGColor];
|
||||
_colorTrackLayer.cornerRadius = 2.0;
|
||||
[self.layer addSublayer:self.colorTrackLayer];
|
||||
|
||||
// The thumb is its own CALayer, which brings in free animation
|
||||
_thumbLayer = [CALayer layer];
|
||||
[self.layer addSublayer:self.thumbLayer];
|
||||
|
||||
self.multipleTouchEnabled = NO;
|
||||
[self layoutTrack];
|
||||
}
|
||||
|
||||
- (void)drawTrack {
|
||||
const CGContextRef ctx = UIGraphicsGetCurrentContext();
|
||||
|
||||
// Track
|
||||
switch(self.trackStyle) {
|
||||
case ComponentStyleRectangular:
|
||||
CGContextAddRect(ctx, self.trackRectangle);
|
||||
break;
|
||||
|
||||
|
||||
case ComponentStyleInvisible:
|
||||
// Nothing to draw
|
||||
break;
|
||||
|
||||
case ComponentStyleRounded:
|
||||
case ComponentStyleIOS:
|
||||
default: {
|
||||
UIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:self.trackRectangle
|
||||
cornerRadius:self.trackRectangle.size.height/2];
|
||||
CGContextAddPath(ctx, [path CGPath]) ;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Ticks
|
||||
if(ComponentStyleIOS != self.tickStyle) {
|
||||
NSAssert(nil != self.ticksAbscisses, @"ticksAbscisses");
|
||||
if(nil != self.ticksAbscisses) {
|
||||
|
||||
for(NSValue * originValue in self.ticksAbscisses) {
|
||||
CGPoint originPoint = [originValue CGPointValue];
|
||||
CGRect rectangle = CGRectMake(originPoint.x-(self.tickSize.width/2),
|
||||
originPoint.y-(self.tickSize.height/2),
|
||||
self.tickSize.width, self.tickSize.height);
|
||||
switch(self.tickStyle) {
|
||||
case ComponentStyleRounded: {
|
||||
UIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:rectangle
|
||||
cornerRadius:rectangle.size.height/2];
|
||||
CGContextAddPath(ctx, [path CGPath]) ;
|
||||
break;
|
||||
}
|
||||
|
||||
case ComponentStyleRectangular:
|
||||
CGContextAddRect(ctx, rectangle);
|
||||
break;
|
||||
|
||||
case ComponentStyleInvisible:
|
||||
case ComponentStyleIOS:
|
||||
default:
|
||||
// Nothing to draw
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // iOS UISlider does not have ticks
|
||||
|
||||
CGContextSetFillColor(ctx, CGColorGetComponents([self.tintColor CGColor]));
|
||||
CGContextFillPath(ctx);
|
||||
|
||||
// For colored track, we overlay a CALayer, which will animate along with the cursor
|
||||
if(ComponentStyleIOS == self.trackStyle) {
|
||||
self.colorTrackLayer.frame = ({
|
||||
CGRect frame = self.trackRectangle;
|
||||
frame.size.width = self.thumbAbscisse - CGRectGetMinX(self.trackRectangle);
|
||||
frame;
|
||||
});
|
||||
} else {
|
||||
self.colorTrackLayer.frame = CGRectZero;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)drawThumb {
|
||||
const CGSize thumbSizeForStyle = [self thumbSizeIncludingShadow];
|
||||
const CGFloat thumbWidth = thumbSizeForStyle.width;
|
||||
const CGFloat thumbHeight = thumbSizeForStyle.height;
|
||||
const CGRect rectangle = CGRectMake(self.thumbAbscisse - (thumbWidth / 2),
|
||||
(self.frame.size.height - thumbHeight)/2,
|
||||
thumbWidth,
|
||||
thumbHeight);
|
||||
|
||||
const CGFloat shadowRadius = ((self.thumbStyle == ComponentStyleIOS)
|
||||
? iOSThumbShadowRadius
|
||||
: self.thumbShadowRadius);
|
||||
const CGSize shadowOffset = ((self.thumbStyle == ComponentStyleIOS)
|
||||
? iosThumbShadowOffset
|
||||
: self.thumbShadowOffset);
|
||||
|
||||
self.thumbLayer.frame = ((shadowRadius != 0.0) // Ignore offset if there is no shadow
|
||||
? CGRectInset(rectangle,
|
||||
shadowRadius + shadowOffset.width,
|
||||
shadowRadius + shadowOffset.height)
|
||||
: CGRectInset(rectangle, shadowRadius, shadowRadius));
|
||||
|
||||
switch(self.thumbStyle) {
|
||||
case ComponentStyleRounded: // A rounded thumb is circular
|
||||
self.thumbLayer.backgroundColor = [self.thumbColor CGColor];
|
||||
self.thumbLayer.borderColor = [[UIColor clearColor] CGColor];
|
||||
self.thumbLayer.borderWidth = 0.0;
|
||||
self.thumbLayer.cornerRadius = self.thumbLayer.frame.size.width/2;
|
||||
self.thumbLayer.allowsEdgeAntialiasing = YES;
|
||||
break;
|
||||
|
||||
case ComponentStyleRectangular:
|
||||
self.thumbLayer.backgroundColor = [self.thumbColor CGColor];
|
||||
self.thumbLayer.borderColor = [[UIColor clearColor] CGColor];
|
||||
self.thumbLayer.borderWidth = 0.0;
|
||||
self.thumbLayer.cornerRadius = 0.0;
|
||||
self.thumbLayer.allowsEdgeAntialiasing = NO;
|
||||
break;
|
||||
|
||||
case ComponentStyleInvisible:
|
||||
self.thumbLayer.backgroundColor = [[UIColor clearColor] CGColor];
|
||||
self.thumbLayer.cornerRadius = 0.0;
|
||||
break;
|
||||
|
||||
case ComponentStyleIOS:
|
||||
default:
|
||||
self.thumbLayer.backgroundColor = [[UIColor whiteColor] CGColor];
|
||||
self.thumbLayer.borderColor = [[UIColor colorWithHue:0 saturation: 0 brightness: 0.8 alpha: 1]
|
||||
CGColor];
|
||||
self.thumbLayer.borderWidth = 0.5;
|
||||
self.thumbLayer.cornerRadius = self.thumbLayer.frame.size.width/2;
|
||||
self.thumbLayer.allowsEdgeAntialiasing = YES;
|
||||
break;
|
||||
}
|
||||
|
||||
// Shadow
|
||||
if(shadowRadius != 0.0) {
|
||||
#if TARGET_INTERFACE_BUILDER
|
||||
self.thumbLayer.shadowOffset = CGSizeMake(shadowOffset.width, -shadowOffset.height);
|
||||
#else // !TARGET_INTERFACE_BUILDER
|
||||
self.thumbLayer.shadowOffset = shadowOffset;
|
||||
#endif // TARGET_INTERFACE_BUILDER
|
||||
|
||||
self.thumbLayer.shadowRadius = shadowRadius;
|
||||
self.thumbLayer.shadowColor = [[UIColor blackColor] CGColor];
|
||||
self.thumbLayer.shadowOpacity = 0.15;
|
||||
} else {
|
||||
self.thumbLayer.shadowRadius = 0.0;
|
||||
self.thumbLayer.shadowOffset = CGSizeZero;
|
||||
self.thumbLayer.shadowColor = [[UIColor clearColor] CGColor];
|
||||
self.thumbLayer.shadowOpacity = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)layoutTrack {
|
||||
NSAssert1(self.tickCount > 1, @"2 ticks minimum %d", self.tickCount);
|
||||
const unsigned int segments = MAX(1, self.tickCount - 1);
|
||||
const CGFloat thumbWidth = [self thumbSizeIncludingShadow].width;
|
||||
const double trackLength = (double)(self.frame.size.width - thumbWidth);
|
||||
|
||||
// Calculate the track ticks positions
|
||||
const CGFloat trackHeight = ((ComponentStyleIOS == self.trackStyle)
|
||||
? 2.0
|
||||
: self.trackThickness);
|
||||
self.trackRectangle = CGRectMake(thumbWidth/2, (self.frame.size.height - trackHeight)/2,
|
||||
self.frame.size.width - thumbWidth, trackHeight);
|
||||
const CGFloat trackY = self.frame.size.height / 2;
|
||||
[self.ticksAbscisses removeAllObjects];
|
||||
for( int iterate = 0; iterate <= segments; iterate++) {
|
||||
const double ratio = (double)iterate / (double)segments;
|
||||
const CGFloat originX = (thumbWidth / 2) + (CGFloat)(trackLength * ratio);
|
||||
[self.ticksAbscisses addObject: [NSValue valueWithCGPoint:CGPointMake(originX, trackY)]];
|
||||
}
|
||||
|
||||
[self layoutThumb];
|
||||
}
|
||||
|
||||
- (void)layoutThumb {
|
||||
NSAssert1(self.tickCount > 1, @"2 ticks minimum %d", self.tickCount);
|
||||
const unsigned int segments = MAX(1, self.tickCount - 1);
|
||||
const CGFloat thumbWidth = [self thumbSizeIncludingShadow].width;
|
||||
const double trackLength = (double)(self.frame.size.width - thumbWidth);
|
||||
|
||||
// Calculate the thumb position
|
||||
const unsigned int nonZeroIncrement = ((0 == self.incrementValue) ? 1 : self.incrementValue);
|
||||
double thumbRatio = (double)(self.value - self.minimumValue) / (double)(segments * nonZeroIncrement);
|
||||
thumbRatio = MAX(0.0, MIN(thumbRatio, 1.0)); // Normalized
|
||||
self.thumbAbscisse = (thumbWidth / 2) + (CGFloat)(trackLength * thumbRatio);
|
||||
}
|
||||
|
||||
- (CGSize)thumbSizeIncludingShadow {
|
||||
switch (self.thumbStyle) {
|
||||
case ComponentStyleInvisible:
|
||||
return CGSizeZero;
|
||||
|
||||
case ComponentStyleRectangular:
|
||||
case ComponentStyleRounded:
|
||||
return ((self.thumbShadowRadius != 0.0)
|
||||
? CGSizeMake(self.thumbSize.width
|
||||
+ (self.thumbShadowRadius * 2)
|
||||
+ (self.thumbShadowOffset.width * 2),
|
||||
self.thumbSize.height
|
||||
+ (self.thumbShadowRadius * 2)
|
||||
+ (self.thumbShadowOffset.height * 2))
|
||||
: self.thumbSize);
|
||||
|
||||
case ComponentStyleIOS:
|
||||
return CGSizeMake(33.0
|
||||
+ (iOSThumbShadowRadius * 2)
|
||||
+ (iosThumbShadowOffset.width * 2),
|
||||
33.0
|
||||
+ (iOSThumbShadowRadius * 2)
|
||||
+ (iosThumbShadowOffset.height * 2));
|
||||
|
||||
default:
|
||||
return (CGSize){33.0, 33.0};
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark UIControl
|
||||
|
||||
- (void)sendActionsForControlEvents {
|
||||
// Interface builder hides the IBInspectable for UIControl
|
||||
#if !TARGET_INTERFACE_BUILDER
|
||||
[self sendActionsForControlEvents:UIControlEventValueChanged];
|
||||
#endif // !TARGET_INTERFACE_BUILDER
|
||||
}
|
||||
|
||||
#pragma mark Touches
|
||||
|
||||
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
|
||||
[self touchDown:touches duration:0.1];
|
||||
}
|
||||
|
||||
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
|
||||
[self touchDown:touches duration:0.0];
|
||||
}
|
||||
|
||||
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
|
||||
[self touchUp:touches];
|
||||
}
|
||||
|
||||
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
|
||||
[self touchUp:touches];
|
||||
}
|
||||
|
||||
- (void)touchDown:(NSSet *)touches duration:(NSTimeInterval)duration {
|
||||
const UITouch * touch = [touches anyObject];
|
||||
if(nil != touch) {
|
||||
const CGPoint location = [touch locationInView:touch.view];
|
||||
[self moveThumbTo:location.x duration:duration];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)touchUp:(NSSet *)touches {
|
||||
const UITouch * touch = [touches anyObject];
|
||||
if(nil != touch) {
|
||||
const CGPoint location = [touch locationInView:touch.view];
|
||||
const unsigned int tick = [self pickTickFromSliderPosition:location.x];
|
||||
[self moveThumbToTick:tick];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark Notifications
|
||||
|
||||
- (void)moveThumbToTick:(unsigned int)tick {
|
||||
const unsigned int nonZeroIncrement = ((0 == self.incrementValue) ? 1 : self.incrementValue);
|
||||
_intValue = self.minimumValue + (tick * nonZeroIncrement);
|
||||
[self sendActionsForControlEvents];
|
||||
|
||||
[self layoutThumb];
|
||||
[self setNeedsDisplay];
|
||||
}
|
||||
|
||||
- (void)moveThumbTo:(CGFloat)abscisse duration:(CFTimeInterval)duration {
|
||||
const CGFloat leftMost = CGRectGetMinX(self.trackRectangle);
|
||||
const CGFloat rightMost = CGRectGetMaxX(self.trackRectangle);
|
||||
|
||||
self.thumbAbscisse = MAX(leftMost, MIN(abscisse, rightMost));
|
||||
[CATransaction setAnimationDuration:duration];
|
||||
|
||||
const unsigned int tick = [self pickTickFromSliderPosition:self.thumbAbscisse];
|
||||
const unsigned int nonZeroIncrement = ((0 == self.incrementValue) ? 1 : self.incrementValue);
|
||||
_intValue = self.minimumValue + (tick * nonZeroIncrement);
|
||||
[self sendActionsForControlEvents];
|
||||
|
||||
[self setNeedsDisplay];
|
||||
}
|
||||
|
||||
- (unsigned int)pickTickFromSliderPosition:(CGFloat)abscisse {
|
||||
const CGFloat leftMost = CGRectGetMinX(self.trackRectangle);
|
||||
const CGFloat rightMost = CGRectGetMaxX(self.trackRectangle);
|
||||
const CGFloat clampedAbscisse = MAX(leftMost, MIN(abscisse, rightMost));
|
||||
const double ratio = (double)(clampedAbscisse - leftMost) / (double)(rightMost - leftMost);
|
||||
const unsigned int segments = MAX(1, self.tickCount - 1);
|
||||
return (unsigned int) round( (double)segments * ratio);
|
||||
}
|
||||
|
||||
#pragma mark - Interface Builder
|
||||
|
||||
#if TARGET_INTERFACE_BUILDER
|
||||
// Interface builder hides the IBInspectable for UIControl
|
||||
- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents {}
|
||||
#endif // TARGET_INTERFACE_BUILDER
|
||||
|
||||
@end
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.thegothicparty.$(PRODUCT_NAME:rfc1034identifier)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
Copyright (c) 2014 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.
|
||||
Loading…
Reference in New Issue