First cut refactor secure
This commit is contained in:
parent
35523f5ec7
commit
344eab8512
|
@ -1,3 +1,4 @@
|
|||
DSFFloatLabelledTextControls.xcodeproj/xcuserdata
|
||||
xcschememanagement.plist
|
||||
.swiftpm
|
||||
Demos/DSFFloatLabelledTextControls.xcodeproj/xcuserdata
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = "DSFFloatLabelledTextControl"
|
||||
s.version = "1.8.0"
|
||||
s.summary = "A macOS Cocoa single-line NSTextField that implements the Float Label Pattern"
|
||||
s.summary = "A macOS Cocoa single-line NSTextField/NSSecureTextField that implements the Float Label Pattern"
|
||||
s.description = <<-DESC
|
||||
A macOS Cocoa single-line NSTextField that implements the Float Label Pattern. Supports secure edit fields.
|
||||
A macOS Cocoa single-line NSTextField/NSSecureTextField that implements the Float Label Pattern.
|
||||
DESC
|
||||
s.homepage = "https://github.com/dagronf/DSFFloatLabelledTextControl"
|
||||
s.license = { :type => "MIT", :file => "LICENSE" }
|
||||
|
@ -11,7 +11,7 @@ Pod::Spec.new do |s|
|
|||
s.social_media_url = ""
|
||||
s.osx.deployment_target = "10.11"
|
||||
s.source = { :git => ".git", :tag => s.version.to_s }
|
||||
s.source_files = "DSFFloatLabelledTextControl/DSFFloatLabelledTextField.swift"
|
||||
s.source_files = "Sources/DSFFloatLabelledTextControl/*.swift"
|
||||
s.frameworks = "Cocoa"
|
||||
s.swift_version = "5.0"
|
||||
s.swift_version = "5.4"
|
||||
end
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
<?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>SchemeUserState</key>
|
||||
<dict>
|
||||
<key>All.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>4</integer>
|
||||
</dict>
|
||||
<key>DSFFloatLabelledTextControl.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
<key>DSFFloatLabelledTextControls Demo objc.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>3</integer>
|
||||
</dict>
|
||||
<key>DSFFloatLabelledTextControls RTL.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
<key>DSFFloatLabelledTextControls.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<key>DSFFloatLabelledTextField.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>2</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>SuppressBuildableAutocreation</key>
|
||||
<dict>
|
||||
<key>2351F84A2207D15C00EFA4F7</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>23A2B7E8220792FE00B2FC77</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>23C3AB9923FBCFA30079D9C3</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
|
@ -3,7 +3,7 @@
|
|||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 50;
|
||||
objectVersion = 52;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXAggregateTarget section */
|
||||
|
@ -22,38 +22,18 @@
|
|||
/* End PBXAggregateTarget section */
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
2351F84F2207D15C00EFA4F7 /* DSFFloatLabelledTextControl.h in Headers */ = {isa = PBXBuildFile; fileRef = 2351F84D2207D15C00EFA4F7 /* DSFFloatLabelledTextControl.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
2351F8522207D15C00EFA4F7 /* DSFFloatLabelledTextField.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2351F84B2207D15C00EFA4F7 /* DSFFloatLabelledTextField.framework */; };
|
||||
2351F8532207D15C00EFA4F7 /* DSFFloatLabelledTextField.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 2351F84B2207D15C00EFA4F7 /* DSFFloatLabelledTextField.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
2351F8582207D16100EFA4F7 /* DSFFloatLabelledTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23A2B7FA2207931500B2FC77 /* DSFFloatLabelledTextField.swift */; };
|
||||
2351F85B22082AD800EFA4F7 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = 2351F85922082AD800EFA4F7 /* LICENSE */; };
|
||||
2351F85C22082AD800EFA4F7 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 2351F85A22082AD800EFA4F7 /* README.md */; };
|
||||
23A2B7ED220792FE00B2FC77 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23A2B7EC220792FE00B2FC77 /* AppDelegate.swift */; };
|
||||
23A2B7EF220792FF00B2FC77 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 23A2B7EE220792FF00B2FC77 /* Assets.xcassets */; };
|
||||
23A2B7F2220792FF00B2FC77 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 23A2B7F0220792FF00B2FC77 /* MainMenu.xib */; };
|
||||
23A3061C29C12CB200BEC98A /* DSFFloatLabelledTextField in Frameworks */ = {isa = PBXBuildFile; productRef = 23A3061B29C12CB200BEC98A /* DSFFloatLabelledTextField */; };
|
||||
23A3061E29C12CB800BEC98A /* DSFFloatLabelledTextField in Frameworks */ = {isa = PBXBuildFile; productRef = 23A3061D29C12CB800BEC98A /* DSFFloatLabelledTextField */; };
|
||||
23C3AB9E23FBCFA30079D9C3 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 23C3AB9D23FBCFA30079D9C3 /* AppDelegate.m */; };
|
||||
23C3ABA023FBCFA40079D9C3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 23C3AB9F23FBCFA40079D9C3 /* Assets.xcassets */; };
|
||||
23C3ABA323FBCFA40079D9C3 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 23C3ABA123FBCFA40079D9C3 /* MainMenu.xib */; };
|
||||
23C3ABA623FBCFA40079D9C3 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 23C3ABA523FBCFA40079D9C3 /* main.m */; };
|
||||
23C3ABAC23FBCFDE0079D9C3 /* DSFFloatLabelledTextField.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2351F84B2207D15C00EFA4F7 /* DSFFloatLabelledTextField.framework */; };
|
||||
23C3ABB023FBD0F80079D9C3 /* DSFFloatLabelledTextField.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 2351F84B2207D15C00EFA4F7 /* DSFFloatLabelledTextField.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
2351F8502207D15C00EFA4F7 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 23A2B7E1220792FE00B2FC77 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 2351F84A2207D15C00EFA4F7;
|
||||
remoteInfo = DSFFloatLabelledTextControl;
|
||||
};
|
||||
23C3ABAD23FBCFE40079D9C3 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 23A2B7E1220792FE00B2FC77 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 2351F84A2207D15C00EFA4F7;
|
||||
remoteInfo = DSFFloatLabelledTextField;
|
||||
};
|
||||
23E825672575D17E0023A3C7 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 23A2B7E1220792FE00B2FC77 /* Project object */;
|
||||
|
@ -77,7 +57,6 @@
|
|||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
2351F8532207D15C00EFA4F7 /* DSFFloatLabelledTextField.framework in Embed Frameworks */,
|
||||
);
|
||||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
@ -88,26 +67,19 @@
|
|||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
23C3ABB023FBD0F80079D9C3 /* DSFFloatLabelledTextField.framework in CopyFiles */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
2351F84B2207D15C00EFA4F7 /* DSFFloatLabelledTextField.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DSFFloatLabelledTextField.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
2351F84D2207D15C00EFA4F7 /* DSFFloatLabelledTextControl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DSFFloatLabelledTextControl.h; sourceTree = "<group>"; };
|
||||
2351F84E2207D15C00EFA4F7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
2351F85922082AD800EFA4F7 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
|
||||
2351F85A22082AD800EFA4F7 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
|
||||
23A2B7E9220792FE00B2FC77 /* DSFFloatLabelledTextControls.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DSFFloatLabelledTextControls.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
23A2B7EC220792FE00B2FC77 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
23A2B7EE220792FF00B2FC77 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
23A2B7F1220792FF00B2FC77 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
|
||||
23A2B7F3220792FF00B2FC77 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
23A2B7F4220792FF00B2FC77 /* DSFFloatLabelledTextControls.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DSFFloatLabelledTextControls.entitlements; sourceTree = "<group>"; };
|
||||
23A2B7FA2207931500B2FC77 /* DSFFloatLabelledTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DSFFloatLabelledTextField.swift; sourceTree = "<group>"; };
|
||||
23ACF96D228A3F6600FF6594 /* DSFFloatLabelledTextControl.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; path = DSFFloatLabelledTextControl.podspec; sourceTree = "<group>"; };
|
||||
23A3061A29C12C9C00BEC98A /* DSFFloatLabelledTextControls */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = DSFFloatLabelledTextControls; path = ..; sourceTree = "<group>"; };
|
||||
23C3AB9A23FBCFA30079D9C3 /* DSFFloatLabelledTextControls Demo objc.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "DSFFloatLabelledTextControls Demo objc.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
23C3AB9C23FBCFA30079D9C3 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
||||
23C3AB9D23FBCFA30079D9C3 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
||||
|
@ -117,22 +89,14 @@
|
|||
23C3ABA523FBCFA40079D9C3 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
23C3ABA723FBCFA40079D9C3 /* DSFFloatLabelledTextControls_Demo_objc.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DSFFloatLabelledTextControls_Demo_objc.entitlements; sourceTree = "<group>"; };
|
||||
23E8256D2575D28A0023A3C7 /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/MainMenu.strings; sourceTree = "<group>"; };
|
||||
23FFF1CD23BD490F008FA55A /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
2351F8482207D15C00EFA4F7 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
23A2B7E6220792FE00B2FC77 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
2351F8522207D15C00EFA4F7 /* DSFFloatLabelledTextField.framework in Frameworks */,
|
||||
23A3061C29C12CB200BEC98A /* DSFFloatLabelledTextField in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -140,32 +104,18 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
23C3ABAC23FBCFDE0079D9C3 /* DSFFloatLabelledTextField.framework in Frameworks */,
|
||||
23A3061E29C12CB800BEC98A /* DSFFloatLabelledTextField in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
2351F84C2207D15C00EFA4F7 /* DSFFloatLabelledTextField */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
23A2B7FA2207931500B2FC77 /* DSFFloatLabelledTextField.swift */,
|
||||
2351F84D2207D15C00EFA4F7 /* DSFFloatLabelledTextControl.h */,
|
||||
2351F84E2207D15C00EFA4F7 /* Info.plist */,
|
||||
);
|
||||
path = DSFFloatLabelledTextField;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
23A2B7E0220792FE00B2FC77 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
23A3061A29C12C9C00BEC98A /* DSFFloatLabelledTextControls */,
|
||||
23FFF1CF23BD4982008FA55A /* Demos */,
|
||||
23FFF1CE23BD496A008FA55A /* Sources */,
|
||||
23ACF96D228A3F6600FF6594 /* DSFFloatLabelledTextControl.podspec */,
|
||||
2351F85922082AD800EFA4F7 /* LICENSE */,
|
||||
2351F85A22082AD800EFA4F7 /* README.md */,
|
||||
23FFF1CD23BD490F008FA55A /* Package.swift */,
|
||||
23A2B7EA220792FE00B2FC77 /* Products */,
|
||||
23C3ABAB23FBCFDE0079D9C3 /* Frameworks */,
|
||||
);
|
||||
|
@ -175,7 +125,6 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
23A2B7E9220792FE00B2FC77 /* DSFFloatLabelledTextControls.app */,
|
||||
2351F84B2207D15C00EFA4F7 /* DSFFloatLabelledTextField.framework */,
|
||||
23C3AB9A23FBCFA30079D9C3 /* DSFFloatLabelledTextControls Demo objc.app */,
|
||||
);
|
||||
name = Products;
|
||||
|
@ -214,14 +163,6 @@
|
|||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
23FFF1CE23BD496A008FA55A /* Sources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2351F84C2207D15C00EFA4F7 /* DSFFloatLabelledTextField */,
|
||||
);
|
||||
path = Sources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
23FFF1CF23BD4982008FA55A /* Demos */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -233,36 +174,7 @@
|
|||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
2351F8462207D15C00EFA4F7 /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
2351F84F2207D15C00EFA4F7 /* DSFFloatLabelledTextControl.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXHeadersBuildPhase section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
2351F84A2207D15C00EFA4F7 /* DSFFloatLabelledTextField */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 2351F8542207D15C00EFA4F7 /* Build configuration list for PBXNativeTarget "DSFFloatLabelledTextField" */;
|
||||
buildPhases = (
|
||||
2351F8462207D15C00EFA4F7 /* Headers */,
|
||||
2351F8472207D15C00EFA4F7 /* Sources */,
|
||||
2351F8482207D15C00EFA4F7 /* Frameworks */,
|
||||
2351F8492207D15C00EFA4F7 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = DSFFloatLabelledTextField;
|
||||
productName = DSFFloatLabelledTextControl;
|
||||
productReference = 2351F84B2207D15C00EFA4F7 /* DSFFloatLabelledTextField.framework */;
|
||||
productType = "com.apple.product-type.framework";
|
||||
};
|
||||
23A2B7E8220792FE00B2FC77 /* DSFFloatLabelledTextControls */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 23A2B7F7220792FF00B2FC77 /* Build configuration list for PBXNativeTarget "DSFFloatLabelledTextControls" */;
|
||||
|
@ -275,9 +187,11 @@
|
|||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
2351F8512207D15C00EFA4F7 /* PBXTargetDependency */,
|
||||
);
|
||||
name = DSFFloatLabelledTextControls;
|
||||
packageProductDependencies = (
|
||||
23A3061B29C12CB200BEC98A /* DSFFloatLabelledTextField */,
|
||||
);
|
||||
productName = DSFFloatLabelledTextControls;
|
||||
productReference = 23A2B7E9220792FE00B2FC77 /* DSFFloatLabelledTextControls.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
|
@ -294,9 +208,11 @@
|
|||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
23C3ABAE23FBCFE40079D9C3 /* PBXTargetDependency */,
|
||||
);
|
||||
name = "DSFFloatLabelledTextControls Demo objc";
|
||||
packageProductDependencies = (
|
||||
23A3061D29C12CB800BEC98A /* DSFFloatLabelledTextField */,
|
||||
);
|
||||
productName = "DSFFloatLabelledTextControls Demo objc";
|
||||
productReference = 23C3AB9A23FBCFA30079D9C3 /* DSFFloatLabelledTextControls Demo objc.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
|
@ -311,9 +227,6 @@
|
|||
LastUpgradeCheck = 1010;
|
||||
ORGANIZATIONNAME = "Darren Ford";
|
||||
TargetAttributes = {
|
||||
2351F84A2207D15C00EFA4F7 = {
|
||||
CreatedOnToolsVersion = 10.1;
|
||||
};
|
||||
23A2B7E8220792FE00B2FC77 = {
|
||||
CreatedOnToolsVersion = 10.1;
|
||||
};
|
||||
|
@ -339,7 +252,6 @@
|
|||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
2351F84A2207D15C00EFA4F7 /* DSFFloatLabelledTextField */,
|
||||
23A2B7E8220792FE00B2FC77 /* DSFFloatLabelledTextControls */,
|
||||
23C3AB9923FBCFA30079D9C3 /* DSFFloatLabelledTextControls Demo objc */,
|
||||
23E825612575D1760023A3C7 /* All */,
|
||||
|
@ -348,20 +260,11 @@
|
|||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
2351F8492207D15C00EFA4F7 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
23A2B7E7220792FE00B2FC77 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
2351F85B22082AD800EFA4F7 /* LICENSE in Resources */,
|
||||
23A2B7EF220792FF00B2FC77 /* Assets.xcassets in Resources */,
|
||||
2351F85C22082AD800EFA4F7 /* README.md in Resources */,
|
||||
23A2B7F2220792FF00B2FC77 /* MainMenu.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
@ -378,14 +281,6 @@
|
|||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
2351F8472207D15C00EFA4F7 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
2351F8582207D16100EFA4F7 /* DSFFloatLabelledTextField.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
23A2B7E5220792FE00B2FC77 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
@ -406,16 +301,6 @@
|
|||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
2351F8512207D15C00EFA4F7 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 2351F84A2207D15C00EFA4F7 /* DSFFloatLabelledTextField */;
|
||||
targetProxy = 2351F8502207D15C00EFA4F7 /* PBXContainerItemProxy */;
|
||||
};
|
||||
23C3ABAE23FBCFE40079D9C3 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 2351F84A2207D15C00EFA4F7 /* DSFFloatLabelledTextField */;
|
||||
targetProxy = 23C3ABAD23FBCFE40079D9C3 /* PBXContainerItemProxy */;
|
||||
};
|
||||
23E825682575D17E0023A3C7 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 23A2B7E8220792FE00B2FC77 /* DSFFloatLabelledTextControls */;
|
||||
|
@ -449,66 +334,6 @@
|
|||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
2351F8552207D15C00EFA4F7 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
FRAMEWORK_VERSION = A;
|
||||
INFOPLIST_FILE = Sources/DSFFloatLabelledTextField/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.5;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.darrenford.DSFFloatLabelledTextControl;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_VERSION = 4.2;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
2351F8562207D15C00EFA4F7 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
FRAMEWORK_VERSION = A;
|
||||
INFOPLIST_FILE = Sources/DSFFloatLabelledTextField/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.5;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.darrenford.DSFFloatLabelledTextControl;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_VERSION = 4.2;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
23A2B7F5220792FF00B2FC77 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
|
@ -629,7 +454,6 @@
|
|||
23A2B7F8220792FF00B2FC77 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = "";
|
||||
CODE_SIGN_ENTITLEMENTS = Demos/DSFFloatLabelledTextControls/DSFFloatLabelledTextControls.entitlements;
|
||||
|
@ -642,6 +466,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
MARKETING_VERSION = 1.5;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.darrenford.DSFFloatLabelledTextControls;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
@ -653,7 +478,6 @@
|
|||
23A2B7F9220792FF00B2FC77 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = "";
|
||||
CODE_SIGN_ENTITLEMENTS = Demos/DSFFloatLabelledTextControls/DSFFloatLabelledTextControls.entitlements;
|
||||
|
@ -666,6 +490,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
MARKETING_VERSION = 1.5;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.darrenford.DSFFloatLabelledTextControls;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
@ -680,17 +505,17 @@
|
|||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_ENTITLEMENTS = "Demos/DSFFloatLabelledTextControls Demo objc/DSFFloatLabelledTextControls_Demo_objc.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEVELOPMENT_TEAM = 3L6RK3LGGW;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
INFOPLIST_FILE = "Demos/DSFFloatLabelledTextControls Demo objc/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.darrenford.DSFFloatLabelledTextControls-Demo-objc";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
|
@ -702,17 +527,17 @@
|
|||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_ENTITLEMENTS = "Demos/DSFFloatLabelledTextControls Demo objc/DSFFloatLabelledTextControls_Demo_objc.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEVELOPMENT_TEAM = 3L6RK3LGGW;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
INFOPLIST_FILE = "Demos/DSFFloatLabelledTextControls Demo objc/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.darrenford.DSFFloatLabelledTextControls-Demo-objc";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
|
@ -739,15 +564,6 @@
|
|||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
2351F8542207D15C00EFA4F7 /* Build configuration list for PBXNativeTarget "DSFFloatLabelledTextField" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
2351F8552207D15C00EFA4F7 /* Debug */,
|
||||
2351F8562207D15C00EFA4F7 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
23A2B7E4220792FE00B2FC77 /* Build configuration list for PBXProject "DSFFloatLabelledTextControls" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
@ -785,6 +601,17 @@
|
|||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
|
||||
/* Begin XCSwiftPackageProductDependency section */
|
||||
23A3061B29C12CB200BEC98A /* DSFFloatLabelledTextField */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
productName = DSFFloatLabelledTextField;
|
||||
};
|
||||
23A3061D29C12CB800BEC98A /* DSFFloatLabelledTextField */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
productName = DSFFloatLabelledTextField;
|
||||
};
|
||||
/* End XCSwiftPackageProductDependency section */
|
||||
};
|
||||
rootObject = 23A2B7E1220792FE00B2FC77 /* Project object */;
|
||||
}
|
|
@ -24,7 +24,7 @@
|
|||
// Insert code here to tear down your application
|
||||
}
|
||||
|
||||
- (void)floatLabelledTextFieldContentChanged:(DSFFloatLabelledTextField *)field {
|
||||
- (void)floatLabelledTextFieldContentChanged:(DSFFloatLabelledSecureTextField *)field {
|
||||
NSLog(@"Password is now `%@`", field.stringValue);
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="17506" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21507" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="17506"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21507"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
|
@ -692,7 +692,7 @@
|
|||
<stackView distribution="fill" orientation="vertical" alignment="centerX" horizontalStackHuggingPriority="250" verticalStackHuggingPriority="249.99998474121094" ambiguous="YES" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="5Xn-w2-ecV">
|
||||
<rect key="frame" x="20" y="27" width="440" height="98"/>
|
||||
<subviews>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="1000" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="XPK-cR-iSb" userLabel="Title Field" customClass="DSFFloatLabelledTextField" customModule="DSFFloatLabelledTextField">
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="XPK-cR-iSb" userLabel="Title Field" customClass="DSFFloatLabelledTextField" customModule="DSFFloatLabelledTextField">
|
||||
<rect key="frame" x="0.0" y="66" width="440" height="32"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="border" alignment="left" placeholderString="Title" id="PFO-GA-4nl">
|
||||
<font key="font" metaFont="system" size="24"/>
|
||||
|
@ -705,7 +705,7 @@
|
|||
</userDefinedRuntimeAttribute>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="1000" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="5uu-Hi-xn8" userLabel="Title Field" customClass="DSFFloatLabelledTextField" customModule="DSFFloatLabelledTextField">
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="5uu-Hi-xn8" userLabel="Title Field" customClass="DSFFloatLabelledTextField" customModule="DSFFloatLabelledTextField">
|
||||
<rect key="frame" x="0.0" y="33" width="440" height="25"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="border" alignment="left" placeholderString="Subtitle text goes here" id="Uic-HN-dxQ">
|
||||
<font key="font" metaFont="system" size="18"/>
|
||||
|
@ -718,7 +718,7 @@
|
|||
</userDefinedRuntimeAttribute>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="1000" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="257-gt-5Ui" userLabel="Title Field" customClass="DSFFloatLabelledTextField" customModule="DSFFloatLabelledTextField">
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="257-gt-5Ui" userLabel="Title Field" customClass="DSFFloatLabelledSecureTextField" customModule="DSFFloatLabelledTextField">
|
||||
<rect key="frame" x="0.0" y="0.0" width="440" height="25"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="border" alignment="left" placeholderString="My Secret Password" id="Msd-kf-k0Q">
|
||||
<font key="font" metaFont="system" size="18"/>
|
||||
|
@ -729,7 +729,6 @@
|
|||
<userDefinedRuntimeAttribute type="number" keyPath="placeholderTextSize">
|
||||
<real key="value" value="13"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
<userDefinedRuntimeAttribute type="boolean" keyPath="isSecure" value="YES"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<outlet property="floatLabelDelegate" destination="Voe-Tx-rLC" id="fDf-Y2-VaF"/>
|
|
@ -35,6 +35,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||
@IBOutlet weak var window: NSWindow!
|
||||
@IBOutlet weak var topFloatingLabel: DSFFloatLabelledTextField!
|
||||
|
||||
@IBOutlet weak var secureTextField: DSFFloatLabelledSecureTextField!
|
||||
@IBOutlet weak var passwordFloatingLabel: DSFFloatLabelledTextField!
|
||||
|
||||
func applicationDidFinishLaunching(_ aNotification: Notification) {
|
||||
|
@ -47,26 +48,34 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||
|
||||
let cv = self.window.contentView!
|
||||
|
||||
let x = NSLayoutConstraint(item: ft, attribute: .width,
|
||||
relatedBy: .equal,
|
||||
toItem: nil, attribute: .notAnAttribute,
|
||||
multiplier: 1, constant: 300)
|
||||
let x = NSLayoutConstraint(
|
||||
item: ft, attribute: .width,
|
||||
relatedBy: .equal,
|
||||
toItem: nil, attribute: .notAnAttribute,
|
||||
multiplier: 1, constant: 300
|
||||
)
|
||||
ft.addConstraint(x)
|
||||
cv.addSubview(ft)
|
||||
|
||||
|
||||
|
||||
let x1 = NSLayoutConstraint(item: ft, attribute: .left,
|
||||
relatedBy: .equal,
|
||||
toItem: cv, attribute: .left,
|
||||
multiplier: 1, constant: 20)
|
||||
let x1 = NSLayoutConstraint(
|
||||
item: ft, attribute: .leading,
|
||||
relatedBy: .equal,
|
||||
toItem: cv, attribute: .leading,
|
||||
multiplier: 1, constant: 20
|
||||
)
|
||||
cv.addConstraint(x1)
|
||||
|
||||
let x2 = NSLayoutConstraint(item: ft, attribute: .bottom,
|
||||
relatedBy: .equal,
|
||||
toItem: cv, attribute: .bottom,
|
||||
multiplier: 1, constant: -20)
|
||||
let x2 = NSLayoutConstraint(
|
||||
item: ft, attribute: .bottom,
|
||||
relatedBy: .equal,
|
||||
toItem: cv, attribute: .bottom,
|
||||
multiplier: 1, constant: -20
|
||||
)
|
||||
cv.addConstraint(x2)
|
||||
|
||||
self.secureTextField.stringValue = "caterpillar"
|
||||
}
|
||||
|
||||
@IBAction func resetPressed(_ sender: Any) {
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="17506" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21507" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="17506"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21507"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
|
@ -16,6 +16,7 @@
|
|||
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="DSFFloatLabelledTextControls" customModuleProvider="target">
|
||||
<connections>
|
||||
<outlet property="passwordFloatingLabel" destination="VLP-0u-Kf3" id="9Lw-el-n78"/>
|
||||
<outlet property="secureTextField" destination="VLP-0u-Kf3" id="uDf-HC-5AQ"/>
|
||||
<outlet property="topFloatingLabel" destination="tnz-85-NdV" id="Pyt-zO-up9"/>
|
||||
<outlet property="window" destination="QvC-M9-y7g" id="gIp-Ho-8D9"/>
|
||||
</connections>
|
||||
|
@ -686,19 +687,19 @@
|
|||
<window title="Floating Labels Test" allowsToolTipsWhenApplicationIsInactive="NO" releasedWhenClosed="NO" animationBehavior="default" id="QvC-M9-y7g">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="335" y="390" width="497" height="441"/>
|
||||
<rect key="contentRect" x="335" y="390" width="497" height="592"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1415"/>
|
||||
<view key="contentView" wantsLayer="YES" id="EiT-Mj-1SZ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="497" height="491"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="497" height="592"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<box boxType="secondary" title="Purchase Form" titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="pnz-8U-z2F">
|
||||
<rect key="frame" x="17" y="333" width="463" height="140"/>
|
||||
<view key="contentView" id="fUJ-lp-O9s">
|
||||
<rect key="frame" x="3" y="3" width="457" height="134"/>
|
||||
<rect key="frame" x="17" y="432" width="463" height="142"/>
|
||||
<view key="contentView" ambiguous="YES" id="fUJ-lp-O9s">
|
||||
<rect key="frame" x="4" y="5" width="455" height="134"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="50" verticalHuggingPriority="750" horizontalCompressionResistancePriority="500" verticalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="tnz-85-NdV" userLabel="Title Field" customClass="DSFFloatLabelledTextField" customModule="DSFFloatLabelledTextField">
|
||||
<textField horizontalHuggingPriority="50" verticalHuggingPriority="750" horizontalCompressionResistancePriority="500" verticalCompressionResistancePriority="1000" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="tnz-85-NdV" userLabel="Title Field" customClass="DSFFloatLabelledTextField" customModule="DSFFloatLabelledTextField">
|
||||
<rect key="frame" x="12" y="97" width="374" height="25"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="border" title="Groovy Software v1" placeholderString="Title" id="ETD-Tb-a7N">
|
||||
<font key="font" metaFont="system" size="18"/>
|
||||
|
@ -714,7 +715,7 @@
|
|||
<outlet property="floatLabelDelegate" destination="Voe-Tx-rLC" id="62z-Xl-apm"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<button toolTip="Check for programattic changing of stringValue" horizontalHuggingPriority="999" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="nTi-Ym-3BC">
|
||||
<button toolTip="Check for programattic changing of stringValue" horizontalHuggingPriority="999" verticalHuggingPriority="750" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="nTi-Ym-3BC">
|
||||
<rect key="frame" x="387" y="93" width="69" height="32"/>
|
||||
<buttonCell key="cell" type="push" title="Reset" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="pTp-yr-DKx">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
|
@ -724,7 +725,7 @@
|
|||
<action selector="resetPressed:" target="Voe-Tx-rLC" id="keN-c6-1wD"/>
|
||||
</connections>
|
||||
</button>
|
||||
<box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="pyP-dk-pAy">
|
||||
<box verticalHuggingPriority="750" ambiguous="YES" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="pyP-dk-pAy">
|
||||
<rect key="frame" x="12" y="86" width="437" height="5"/>
|
||||
</box>
|
||||
<textField horizontalHuggingPriority="50" verticalHuggingPriority="750" horizontalCompressionResistancePriority="500" verticalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="zbB-HI-AVu" userLabel="Price Field" customClass="DSFFloatLabelledTextField" customModule="DSFFloatLabelledTextField">
|
||||
|
@ -746,7 +747,7 @@
|
|||
<box horizontalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="Mrp-MT-gGa">
|
||||
<rect key="frame" x="117" y="46" width="5" height="43"/>
|
||||
</box>
|
||||
<textField horizontalHuggingPriority="50" verticalHuggingPriority="750" horizontalCompressionResistancePriority="500" verticalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="SAo-aL-Ofe" userLabel="Location Field" customClass="DSFFloatLabelledTextField" customModule="DSFFloatLabelledTextField">
|
||||
<textField horizontalHuggingPriority="50" verticalHuggingPriority="750" horizontalCompressionResistancePriority="500" verticalCompressionResistancePriority="1000" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="SAo-aL-Ofe" userLabel="Location Field" customClass="DSFFloatLabelledTextField" customModule="DSFFloatLabelledTextField">
|
||||
<rect key="frame" x="128" y="55" width="321" height="25"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="border" placeholderString="Specific Location (Optional)" id="BHQ-MA-tIJ">
|
||||
<font key="font" metaFont="system" size="18"/>
|
||||
|
@ -759,10 +760,10 @@
|
|||
</userDefinedRuntimeAttribute>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</textField>
|
||||
<box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="YiQ-45-hxx">
|
||||
<box verticalHuggingPriority="750" ambiguous="YES" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="YiQ-45-hxx">
|
||||
<rect key="frame" x="12" y="44" width="437" height="5"/>
|
||||
</box>
|
||||
<textField horizontalHuggingPriority="50" verticalHuggingPriority="750" horizontalCompressionResistancePriority="500" translatesAutoresizingMaskIntoConstraints="NO" id="h8z-Ku-xLD" customClass="DSFFloatLabelledTextField" customModule="DSFFloatLabelledTextField">
|
||||
<textField horizontalHuggingPriority="50" verticalHuggingPriority="750" horizontalCompressionResistancePriority="500" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="h8z-Ku-xLD" customClass="DSFFloatLabelledTextField" customModule="DSFFloatLabelledTextField">
|
||||
<rect key="frame" x="12" y="13" width="437" height="25"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="border" placeholderString="Description" id="XtC-Dr-5RL">
|
||||
<font key="font" metaFont="system" size="18"/>
|
||||
|
@ -804,10 +805,10 @@
|
|||
</view>
|
||||
</box>
|
||||
<box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="CVr-p8-VOx">
|
||||
<rect key="frame" x="20" y="303" width="457" height="5"/>
|
||||
<rect key="frame" x="20" y="402" width="457" height="5"/>
|
||||
</box>
|
||||
<stackView distribution="fillEqually" orientation="horizontal" alignment="centerY" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="waN-7O-qLn">
|
||||
<rect key="frame" x="20" y="242" width="457" height="33"/>
|
||||
<rect key="frame" x="20" y="341" width="457" height="33"/>
|
||||
<subviews>
|
||||
<textField horizontalHuggingPriority="50" verticalHuggingPriority="750" horizontalCompressionResistancePriority="500" verticalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="oU9-jl-8Ow" userLabel="Title Field" customClass="DSFFloatLabelledTextField" customModule="DSFFloatLabelledTextField">
|
||||
<rect key="frame" x="0.0" y="0.0" width="50" height="33"/>
|
||||
|
@ -852,10 +853,10 @@
|
|||
</customSpacing>
|
||||
</stackView>
|
||||
<box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="QuB-jf-wmu">
|
||||
<rect key="frame" x="20" y="206" width="457" height="5"/>
|
||||
<rect key="frame" x="20" y="305" width="457" height="5"/>
|
||||
</box>
|
||||
<stackView distribution="fillEqually" orientation="vertical" alignment="centerX" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="CBs-1o-JjM">
|
||||
<rect key="frame" x="20" y="80" width="250" height="112"/>
|
||||
<rect key="frame" x="20" y="179" width="250" height="112"/>
|
||||
<subviews>
|
||||
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="3hp-BV-Ls3" customClass="DSFFloatLabelledTextField" customModule="DSFFloatLabelledTextField">
|
||||
<rect key="frame" x="0.0" y="90" width="250" height="22"/>
|
||||
|
@ -873,7 +874,7 @@
|
|||
</userDefinedRuntimeAttribute>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</textField>
|
||||
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="VLP-0u-Kf3" customClass="DSFFloatLabelledTextField" customModule="DSFFloatLabelledTextField">
|
||||
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="VLP-0u-Kf3" customClass="DSFFloatLabelledSecureTextField" customModule="DSFFloatLabelledTextField">
|
||||
<rect key="frame" x="0.0" y="60" width="250" height="22"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" title="caterpillar" placeholderString="Password" drawsBackground="YES" id="2oD-a4-pQh">
|
||||
<font key="font" metaFont="system" size="14"/>
|
||||
|
@ -887,7 +888,6 @@
|
|||
<userDefinedRuntimeAttribute type="number" keyPath="placeholderSpacing">
|
||||
<real key="value" value="1"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
<userDefinedRuntimeAttribute type="boolean" keyPath="isSecure" value="YES"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<outlet property="floatLabelDelegate" destination="Voe-Tx-rLC" id="IaQ-aC-gRR"/>
|
||||
|
@ -971,7 +971,7 @@
|
|||
<constraint firstItem="pnz-8U-z2F" firstAttribute="top" secondItem="EiT-Mj-1SZ" secondAttribute="top" constant="20" id="zgF-Fx-OjE"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<point key="canvasLocation" x="-480" y="220"/>
|
||||
<point key="canvasLocation" x="-480.5" y="144"/>
|
||||
</window>
|
||||
</objects>
|
||||
</document>
|
|
@ -1,29 +1,23 @@
|
|||
// swift-tools-version:5.1
|
||||
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
||||
// swift-tools-version: 5.4
|
||||
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "DSFFloatLabelledTextField",
|
||||
platforms: [
|
||||
.macOS(.v10_11)
|
||||
],
|
||||
products: [
|
||||
// Products define the executables and libraries produced by a package, and make them visible to other packages.
|
||||
.library(
|
||||
name: "DSFFloatLabelledTextField",
|
||||
targets: ["DSFFloatLabelledTextField"]),
|
||||
],
|
||||
dependencies: [
|
||||
// Dependencies declare other packages that this package depends on.
|
||||
// .package(url: /* package url */, from: "1.0.0"),
|
||||
],
|
||||
targets: [
|
||||
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
|
||||
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
|
||||
.target(
|
||||
name: "DSFFloatLabelledTextField",
|
||||
dependencies: [])
|
||||
],
|
||||
swiftLanguageVersions: [.v5]
|
||||
name: "DSFFloatLabelledTextField",
|
||||
platforms: [
|
||||
.macOS(.v10_11)
|
||||
],
|
||||
products: [
|
||||
.library(
|
||||
name: "DSFFloatLabelledTextField",
|
||||
targets: ["DSFFloatLabelledTextField"]
|
||||
),
|
||||
],
|
||||
targets: [
|
||||
.target(
|
||||
name: "DSFFloatLabelledTextField",
|
||||
dependencies: []
|
||||
)
|
||||
],
|
||||
swiftLanguageVersions: [.v5]
|
||||
)
|
||||
|
|
|
@ -30,10 +30,10 @@ Copy the `DSFFloatLabelledTextField.swift` into your project. This class inheri
|
|||
|
||||
### Interface builder
|
||||
|
||||
* Drop in a new Text Field into your canvas and set its class to `DSFFloatLabelledTextField`
|
||||
* Drop in a new Text Field into your canvas and set its class to `DSFFloatLabelledTextField` or
|
||||
`DSFFloatLabelledSecureTextControl` depending on whether you need a secure field
|
||||
* Set the size and style of your primary font as you would a regular text field
|
||||
* Set the size of the secondary font via the attributes inspector for the control
|
||||
* If you want a secure field, set the `isSecure` property on the control
|
||||
|
||||
### Dynamically
|
||||
|
||||
|
@ -89,7 +89,7 @@ You can specify a delegate (`floatLabelDelegate`), either programatically or via
|
|||
```
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Darren Ford
|
||||
Copyright (c) 2023 Darren Ford
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
|
@ -0,0 +1,451 @@
|
|||
//
|
||||
// DSFFloatLabelledSecureTextField.swift
|
||||
//
|
||||
// Copyright © 2023 Darren Ford. All rights reserved.
|
||||
//
|
||||
// MIT license
|
||||
//
|
||||
// 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 AppKit
|
||||
|
||||
/// DSFFloatLabelledTextField delegate protocol
|
||||
@objc public protocol DSFFloatLabelledSecureTextFieldDelegate: NSObjectProtocol {
|
||||
/// Called when the label is shown or hidden
|
||||
@objc optional func floatLabelledTextField(_ field: DSFFloatLabelledSecureTextField, didShowFloatingLabel didShow: Bool)
|
||||
/// Called when the field becomes or loses first responder status
|
||||
@objc optional func floatLabelledTextField(_ field: DSFFloatLabelledSecureTextField, didFocus: Bool)
|
||||
/// Called when the content of the field changes
|
||||
@objc optional func floatLabelledTextFieldContentChanged(_ field: DSFFloatLabelledSecureTextField)
|
||||
}
|
||||
|
||||
/// An NSSecureTextField that implements the Float Label Pattern
|
||||
@IBDesignable open class DSFFloatLabelledSecureTextField: NSSecureTextField {
|
||||
|
||||
/// Optional delegate to provide callbacks for the floating label state.
|
||||
///
|
||||
/// This delegate can be set via Interface Builder or programatically
|
||||
@IBOutlet @objc public weak var floatLabelDelegate: DSFFloatLabelledSecureTextFieldDelegate?
|
||||
|
||||
/// The size (in pt) of the floating label text
|
||||
@IBInspectable public var placeholderTextSize: CGFloat = NSFont.smallSystemFontSize {
|
||||
didSet {
|
||||
self.floatingLabel.font = NSFont.systemFont(ofSize: self.placeholderTextSize)
|
||||
self.reconfigureControl()
|
||||
}
|
||||
}
|
||||
|
||||
/// Spacing between the floating label and the text field text
|
||||
@IBInspectable public var placeholderSpacing: CGFloat = 0.0 {
|
||||
didSet {
|
||||
self.floatingLabel.font = NSFont.systemFont(ofSize: self.placeholderTextSize)
|
||||
self.reconfigureControl()
|
||||
}
|
||||
}
|
||||
|
||||
// Override so that we can notify when the developer changes the text programatically too
|
||||
open override var stringValue: String {
|
||||
get {
|
||||
return super.stringValue
|
||||
}
|
||||
set {
|
||||
super.stringValue = newValue
|
||||
NotificationCenter.default.post(name: NSControl.textDidChangeNotification, object: self)
|
||||
}
|
||||
}
|
||||
|
||||
// Override so that we can update when the developer changes the placeholder string
|
||||
open override var placeholderString: String? {
|
||||
get {
|
||||
return super.placeholderString
|
||||
}
|
||||
set {
|
||||
super.placeholderString = newValue
|
||||
self.floatingLabel.stringValue = newValue ?? ""
|
||||
}
|
||||
}
|
||||
|
||||
/// Floating label
|
||||
private let floatingLabel = NSTextField()
|
||||
|
||||
/// Is the label currently showing
|
||||
private var isShowing: Bool = false {
|
||||
didSet {
|
||||
self.floatLabelDelegate?.floatLabelledTextField?(self, didShowFloatingLabel: self.isShowing)
|
||||
}
|
||||
}
|
||||
|
||||
/// Constraint to tie the label to the top of the control
|
||||
private var floatingTop: NSLayoutConstraint?
|
||||
|
||||
/// Height of the control
|
||||
private var heightConstraint: NSLayoutConstraint?
|
||||
|
||||
/// Observers for the font and placeholder text
|
||||
private var fontObserver: NSKeyValueObservation?
|
||||
private var placeholderObserver: NSKeyValueObservation?
|
||||
|
||||
/// Returns the height of the placeholder text
|
||||
var placeholderHeight: CGFloat {
|
||||
let layoutManager = NSLayoutManager()
|
||||
return layoutManager.defaultLineHeight(for: self.floatingLabel.font!) + 1
|
||||
}
|
||||
|
||||
/// Returns the height of the primary (editable) text
|
||||
private var textHeight: CGFloat {
|
||||
let layoutManager = NSLayoutManager()
|
||||
return layoutManager.defaultLineHeight(for: self.font!) + 1
|
||||
}
|
||||
|
||||
/// Returns the total height of the control given the font settings
|
||||
private var controlHeight: CGFloat {
|
||||
return self.textHeight + self.placeholderSpacing + self.placeholderHeight
|
||||
}
|
||||
|
||||
open override var intrinsicContentSize: NSSize {
|
||||
var sz = super.intrinsicContentSize
|
||||
sz.height = self.controlHeight
|
||||
return sz
|
||||
}
|
||||
|
||||
func configureCell() {
|
||||
let customCell = DSFFloatLabelledSecureTextFieldCell()
|
||||
customCell.isEditable = true
|
||||
customCell.wraps = false
|
||||
customCell.usesSingleLineMode = true
|
||||
customCell.placeholderString = self.placeholderString
|
||||
customCell.title = self.stringValue
|
||||
customCell.font = self.font
|
||||
customCell.isBordered = self.isBordered
|
||||
customCell.isBezeled = self.isBezeled
|
||||
customCell.bezelStyle = self.bezelStyle
|
||||
customCell.isScrollable = true
|
||||
customCell.isContinuous = self.isContinuous
|
||||
customCell.alignment = self.alignment
|
||||
customCell.formatter = self.formatter
|
||||
customCell.topOffset = self.placeholderHeight
|
||||
self.cell = customCell
|
||||
}
|
||||
|
||||
func setTopOffset(_ value: CGFloat) {
|
||||
guard var f = self.cell as? DSFFloatLabelledTextFieldCellProtocol else {
|
||||
return
|
||||
}
|
||||
f.topOffset = value
|
||||
}
|
||||
|
||||
/// Set the fonts to be used in the control
|
||||
open func setFonts(primary: NSFont, secondary: NSFont) {
|
||||
self.floatingLabel.font = secondary
|
||||
self.font = primary
|
||||
}
|
||||
|
||||
public override init(frame frameRect: NSRect) {
|
||||
super.init(frame: frameRect)
|
||||
self.setup()
|
||||
}
|
||||
|
||||
required public init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
self.setup()
|
||||
}
|
||||
|
||||
open override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
|
||||
}
|
||||
|
||||
open override func viewDidMoveToWindow() {
|
||||
super.viewDidMoveToWindow()
|
||||
|
||||
// When we're added to the view, make sure that the floating label alignment matches us
|
||||
// (as the user might have changed the alignment BEFORE adding to the superview
|
||||
self.floatingLabel.alignment = self.alignment
|
||||
}
|
||||
|
||||
private func setup() {
|
||||
// Setup the common elements of the control
|
||||
self.commonSetup()
|
||||
|
||||
// Configure a default text cell
|
||||
self.configureCell()
|
||||
|
||||
// Listen to changes in the primary font so we can reconfigure to match
|
||||
self.fontObserver = self.observe(\.font, options: [.new]) { [weak self] _, _ in
|
||||
self?.reconfigureControl()
|
||||
}
|
||||
|
||||
// Listen to changes in the placeholder text so we can reflect it in the floater
|
||||
self.placeholderObserver = self.observe(\.placeholderString, options: [.new]) { [weak self] _, _ in
|
||||
guard let `self` = self else { return }
|
||||
self.floatingLabel.stringValue = self.placeholderString!
|
||||
self.reconfigureControl()
|
||||
}
|
||||
}
|
||||
|
||||
/// Build the floating label
|
||||
private func createFloatingLabel() {
|
||||
if self.floatingLabel.superview == nil {
|
||||
self.addSubview(self.floatingLabel)
|
||||
}
|
||||
|
||||
self.floatingLabel.wantsLayer = true
|
||||
self.floatingLabel.isEditable = false
|
||||
self.floatingLabel.isSelectable = false
|
||||
self.floatingLabel.isEnabled = true
|
||||
self.floatingLabel.isBezeled = false
|
||||
self.floatingLabel.isBordered = false
|
||||
self.floatingLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||
self.floatingLabel.font = NSFont.systemFont(ofSize: self.placeholderTextSize)
|
||||
self.floatingLabel.textColor = NSColor.placeholderTextColor
|
||||
self.floatingLabel.stringValue = self.placeholderString ?? ""
|
||||
self.floatingLabel.alphaValue = 0.0
|
||||
self.floatingLabel.alignment = self.alignment
|
||||
self.floatingLabel.drawsBackground = false
|
||||
|
||||
self.floatingTop = NSLayoutConstraint(
|
||||
item: self.floatingLabel, attribute: .top,
|
||||
relatedBy: .equal,
|
||||
toItem: self, attribute: .top,
|
||||
multiplier: 1.0, constant: 10
|
||||
)
|
||||
self.addConstraint(self.floatingTop!)
|
||||
|
||||
var x = NSLayoutConstraint(
|
||||
item: self.floatingLabel, attribute: .leading,
|
||||
relatedBy: .equal,
|
||||
toItem: self, attribute: .leading,
|
||||
multiplier: 1.0, constant: self.isBezeled ? 4 : 0
|
||||
)
|
||||
self.addConstraint(x)
|
||||
|
||||
x = NSLayoutConstraint(
|
||||
item: self.floatingLabel, attribute: .trailing,
|
||||
relatedBy: .equal,
|
||||
toItem: self, attribute: .trailing,
|
||||
multiplier: 1.0, constant: self.isBezeled ? -4 : 0
|
||||
)
|
||||
self.addConstraint(x)
|
||||
|
||||
self.floatingLabel.setContentHuggingPriority(NSLayoutConstraint.Priority(10), for: .horizontal)
|
||||
self.floatingLabel.setContentCompressionResistancePriority(NSLayoutConstraint.Priority(10), for: .horizontal)
|
||||
}
|
||||
|
||||
private func commonSetup() {
|
||||
self.wantsLayer = true
|
||||
self.translatesAutoresizingMaskIntoConstraints = false
|
||||
self.usesSingleLineMode = true
|
||||
self.delegate = self
|
||||
|
||||
// Default to natural layout
|
||||
self.alignment = .natural
|
||||
|
||||
self.createFloatingLabel()
|
||||
|
||||
self.heightConstraint = NSLayoutConstraint(
|
||||
item: self, attribute: .height,
|
||||
relatedBy: .equal,
|
||||
toItem: nil, attribute: .notAnAttribute,
|
||||
multiplier: 1.0, constant: self.controlHeight
|
||||
)
|
||||
self.addConstraint(self.heightConstraint!)
|
||||
|
||||
// If the field already has text, make sure the placeholder is shown
|
||||
if self.stringValue.count > 0 {
|
||||
self.showPlaceholder(animated: false)
|
||||
}
|
||||
}
|
||||
|
||||
/// Change the layout if any changes occur
|
||||
private func reconfigureControl() {
|
||||
if self.isCurrentFocus() {
|
||||
/// If we are currently editing, then finish before changing.
|
||||
self.window?.endEditing(for: nil)
|
||||
}
|
||||
self.expandFrame()
|
||||
}
|
||||
|
||||
/// Rebuild the frame of the text field to match the new settings
|
||||
private func expandFrame() {
|
||||
self.heightConstraint?.constant = self.controlHeight
|
||||
self.setTopOffset(self.placeholderHeight + self.placeholderSpacing)
|
||||
self.needsLayout = true
|
||||
}
|
||||
|
||||
open override func layout() {
|
||||
super.layout()
|
||||
|
||||
self.setTopOffset(self.placeholderHeight + self.placeholderSpacing)
|
||||
self.needsLayout = true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - Focus and editing
|
||||
|
||||
extension DSFFloatLabelledSecureTextField: NSTextFieldDelegate {
|
||||
|
||||
// Change the floating label color to represent active state
|
||||
private func setFloatingLabelActive(_ active: Bool) {
|
||||
if active {
|
||||
self.floatingLabel.textColor = NSColor.simulatedAccentColor
|
||||
}
|
||||
else {
|
||||
self.floatingLabel.textColor = NSColor.placeholderTextColor
|
||||
}
|
||||
|
||||
self.floatLabelDelegate?.floatLabelledTextField?(self, didFocus: active)
|
||||
}
|
||||
|
||||
public func controlTextDidChange(_ obj: Notification) {
|
||||
guard let field = obj.object as? NSTextField else {
|
||||
return
|
||||
}
|
||||
|
||||
if field.stringValue.count > 0, !self.isShowing {
|
||||
self.showPlaceholder(animated: true)
|
||||
}
|
||||
else if field.stringValue.count == 0, self.isShowing {
|
||||
self.hidePlaceholder()
|
||||
}
|
||||
|
||||
self.floatLabelDelegate?.floatLabelledTextFieldContentChanged?(self)
|
||||
}
|
||||
|
||||
open override func becomeFirstResponder() -> Bool {
|
||||
let becomeResult = super.becomeFirstResponder()
|
||||
if becomeResult, self.isCurrentFocus() {
|
||||
// Set the color of the 'label' to match the current focus color.
|
||||
// We need to perform this on the main thread after the current set of notifications are processed
|
||||
// Why? We (occasionally) receive a 'controlTextDidEndEditing' message AFTER we receive a
|
||||
// 'becomeFirstResponder'. I've read that this is related to the text field automatically selecting
|
||||
// text when taking focus, but I haven't been able to verify this in any useful manner.
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
if let `self` = self {
|
||||
self.setFloatingLabelActive(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
return becomeResult
|
||||
}
|
||||
|
||||
open func controlTextDidEndEditing(_: Notification) {
|
||||
// When we lose focus, set the label color back to the placeholder color
|
||||
self.setFloatingLabelActive(false)
|
||||
}
|
||||
|
||||
/// Does our text field currently have input focus?
|
||||
private func isCurrentFocus() -> Bool {
|
||||
// 1. Get the window's first responder
|
||||
// 2. Check is has an active field editor
|
||||
// 3. Is the delegate of the field editor us?
|
||||
if let fr = self.window?.firstResponder as? NSTextView,
|
||||
self.window?.fieldEditor(false, for: nil) != nil,
|
||||
fr.delegate === self {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Animations
|
||||
|
||||
extension DSFFloatLabelledSecureTextField {
|
||||
|
||||
/// Duration of the fade in/out of the secondary label
|
||||
private var animationDuration: TimeInterval {
|
||||
return shouldAnimate() ? 0.4 : 0.0
|
||||
}
|
||||
|
||||
/// Returns true if the system is NOT set to reduce motion (accessibility settings)
|
||||
private func shouldAnimate() -> Bool {
|
||||
if #available(OSX 10.12, *) {
|
||||
return !NSWorkspace.shared.accessibilityDisplayShouldReduceMotion
|
||||
} else {
|
||||
// Fallback on earlier versions. Just animate
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
private func showPlaceholder(animated: Bool) {
|
||||
self.isShowing = true
|
||||
if animated {
|
||||
NSAnimationContext.runAnimationGroup({ [weak self] context in
|
||||
guard let `self` = self else { return }
|
||||
context.allowsImplicitAnimation = true
|
||||
context.duration = self.animationDuration
|
||||
self.floatingTop?.constant = 0
|
||||
self.floatingLabel.alphaValue = 1.0
|
||||
self.layoutSubtreeIfNeeded()
|
||||
}, completionHandler: {
|
||||
//
|
||||
})
|
||||
}
|
||||
else {
|
||||
self.setFloatingLabelActive(false)
|
||||
self.floatingTop?.constant = 0
|
||||
self.floatingLabel.alphaValue = 1.0
|
||||
}
|
||||
}
|
||||
|
||||
private func hidePlaceholder() {
|
||||
self.isShowing = false
|
||||
let duration = self.animationDuration
|
||||
NSAnimationContext.runAnimationGroup({ [weak self] context in
|
||||
guard let `self` = self else { return }
|
||||
context.allowsImplicitAnimation = true
|
||||
context.duration = duration
|
||||
self.floatingTop?.constant = self.textHeight / 1.5
|
||||
self.floatingLabel.alphaValue = 0.0
|
||||
self.layoutSubtreeIfNeeded()
|
||||
}, completionHandler: {
|
||||
//
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Cell definition
|
||||
|
||||
private class DSFFloatLabelledSecureTextFieldCell: NSSecureTextFieldCell, DSFFloatLabelledTextFieldCellProtocol {
|
||||
var topOffset: CGFloat = 0
|
||||
|
||||
private func offset() -> CGFloat {
|
||||
return self.topOffset - (self.isBezeled ? 5 : 1)
|
||||
}
|
||||
|
||||
override func titleRect(forBounds rect: NSRect) -> NSRect {
|
||||
return NSRect(x: rect.origin.x, y: rect.origin.y + self.offset(), width: rect.width, height: rect.height)
|
||||
}
|
||||
|
||||
override func edit(withFrame rect: NSRect, in controlView: NSView, editor textObj: NSText, delegate: Any?, event: NSEvent?) {
|
||||
let insetRect = NSRect(x: rect.origin.x, y: rect.origin.y + self.offset(), width: rect.width, height: rect.height)
|
||||
super.edit(withFrame: insetRect, in: controlView, editor: textObj, delegate: delegate, event: event)
|
||||
}
|
||||
|
||||
override func select(withFrame rect: NSRect, in controlView: NSView, editor textObj: NSText, delegate: Any?, start selStart: Int, length selLength: Int) {
|
||||
let insetRect = NSRect(x: rect.origin.x, y: rect.origin.y + self.offset(), width: rect.width, height: rect.height)
|
||||
super.select(withFrame: insetRect, in: controlView, editor: textObj, delegate: delegate, start: selStart, length: selLength)
|
||||
}
|
||||
|
||||
override func drawInterior(withFrame cellFrame: NSRect, in controlView: NSView) {
|
||||
let insetRect = NSRect(x: cellFrame.origin.x, y: cellFrame.origin.y + self.offset(), width: cellFrame.width, height: cellFrame.height)
|
||||
super.drawInterior(withFrame: insetRect, in: controlView)
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
//
|
||||
// DSFFloatLabelledTextControl.h
|
||||
// DSFFloatLabelledTextControl
|
||||
//
|
||||
// Created by Darren Ford on 4/2/19.
|
||||
// Copyright © 2020 Darren Ford. All rights reserved.
|
||||
//
|
||||
// MIT License
|
||||
//
|
||||
// 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 <Cocoa/Cocoa.h>
|
||||
|
||||
//! Project version number for DSFFloatLabelledTextControl.
|
||||
FOUNDATION_EXPORT double DSFFloatLabelledTextControlVersionNumber;
|
||||
|
||||
//! Project version string for DSFFloatLabelledTextControl.
|
||||
FOUNDATION_EXPORT const unsigned char DSFFloatLabelledTextControlVersionString[];
|
||||
|
||||
// In this header, you should import all the public headers of your framework using statements like #import <DSFFloatLabelledTextControl/PublicHeader.h>
|
||||
|
||||
|
|
@ -1,31 +1,30 @@
|
|||
//
|
||||
// DSFFloatLabelledTextField.swift
|
||||
// DSFFloatLabelledTextControls
|
||||
//
|
||||
// Created by Darren Ford on 4/2/19.
|
||||
// Copyright © 2020 Darren Ford. All rights reserved.
|
||||
// Copyright © 2023 Darren Ford. All rights reserved.
|
||||
//
|
||||
// MIT License
|
||||
// MIT license
|
||||
//
|
||||
// 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:
|
||||
// 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 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.
|
||||
//
|
||||
// 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 Cocoa
|
||||
import AppKit
|
||||
|
||||
/// DSFFloatLabelledTextField delegate protocol
|
||||
@objc public protocol DSFFloatLabelledTextFieldDelegate: NSObjectProtocol {
|
||||
|
@ -61,13 +60,6 @@ import Cocoa
|
|||
}
|
||||
}
|
||||
|
||||
/// Spacing between the floating label and the text field text
|
||||
@IBInspectable public var isSecure: Bool = false {
|
||||
didSet {
|
||||
self.configureCell(isSecure: self.isSecure)
|
||||
}
|
||||
}
|
||||
|
||||
// Override so that we can notify when the developer changes the text programatically too
|
||||
open override var stringValue: String {
|
||||
get {
|
||||
|
@ -133,8 +125,8 @@ import Cocoa
|
|||
return sz
|
||||
}
|
||||
|
||||
func configureCell(isSecure: Bool = false) {
|
||||
let customCell: NSTextFieldCell = isSecure ? DSFFloatLabelledSecureTextFieldCell() : DSFFloatLabelledTextFieldCell()
|
||||
func configureCell() {
|
||||
let customCell = DSFFloatLabelledTextFieldCell()
|
||||
customCell.isEditable = true
|
||||
customCell.wraps = false
|
||||
customCell.usesSingleLineMode = true
|
||||
|
@ -148,10 +140,7 @@ import Cocoa
|
|||
customCell.isContinuous = self.isContinuous
|
||||
customCell.alignment = self.alignment
|
||||
customCell.formatter = self.formatter
|
||||
|
||||
if var s = customCell as? DSFFloatLabelledTextFieldCellProtocol {
|
||||
s.topOffset = self.placeholderHeight
|
||||
}
|
||||
customCell.topOffset = self.placeholderHeight
|
||||
|
||||
self.cell = customCell
|
||||
}
|
||||
|
@ -192,7 +181,7 @@ import Cocoa
|
|||
self.commonSetup()
|
||||
|
||||
// Configure a default text cell
|
||||
self.configureCell(isSecure: false)
|
||||
self.configureCell()
|
||||
|
||||
// Listen to changes in the primary font so we can reconfigure to match
|
||||
self.fontObserver = self.observe(\.font, options: [.new]) { [weak self] _, _ in
|
||||
|
@ -312,7 +301,7 @@ extension DSFFloatLabelledTextField: NSTextFieldDelegate {
|
|||
// Change the floating label color to represent active state
|
||||
private func setFloatingLabelActive(_ active: Bool) {
|
||||
if active {
|
||||
self.floatingLabel.textColor = NSColor.systemAccentColor
|
||||
self.floatingLabel.textColor = NSColor.simulatedAccentColor
|
||||
}
|
||||
else {
|
||||
self.floatingLabel.textColor = NSColor.placeholderTextColor
|
||||
|
@ -430,10 +419,6 @@ extension DSFFloatLabelledTextField {
|
|||
|
||||
// MARK: - Cell definition
|
||||
|
||||
protocol DSFFloatLabelledTextFieldCellProtocol {
|
||||
var topOffset: CGFloat { get set }
|
||||
}
|
||||
|
||||
private class DSFFloatLabelledTextFieldCell: NSTextFieldCell, DSFFloatLabelledTextFieldCellProtocol {
|
||||
var topOffset: CGFloat = 0
|
||||
|
||||
|
@ -460,76 +445,3 @@ private class DSFFloatLabelledTextFieldCell: NSTextFieldCell, DSFFloatLabelledTe
|
|||
super.drawInterior(withFrame: insetRect, in: controlView)
|
||||
}
|
||||
}
|
||||
|
||||
private class DSFFloatLabelledSecureTextFieldCell: NSSecureTextFieldCell, DSFFloatLabelledTextFieldCellProtocol {
|
||||
var topOffset: CGFloat = 0
|
||||
|
||||
private func offset() -> CGFloat {
|
||||
return self.topOffset - (self.isBezeled ? 5 : 1)
|
||||
}
|
||||
|
||||
override func titleRect(forBounds rect: NSRect) -> NSRect {
|
||||
return NSRect(x: rect.origin.x, y: rect.origin.y + self.offset(), width: rect.width, height: rect.height)
|
||||
}
|
||||
|
||||
override func edit(withFrame rect: NSRect, in controlView: NSView, editor textObj: NSText, delegate: Any?, event: NSEvent?) {
|
||||
let insetRect = NSRect(x: rect.origin.x, y: rect.origin.y + self.offset(), width: rect.width, height: rect.height)
|
||||
super.edit(withFrame: insetRect, in: controlView, editor: textObj, delegate: delegate, event: event)
|
||||
}
|
||||
|
||||
override func select(withFrame rect: NSRect, in controlView: NSView, editor textObj: NSText, delegate: Any?, start selStart: Int, length selLength: Int) {
|
||||
let insetRect = NSRect(x: rect.origin.x, y: rect.origin.y + self.offset(), width: rect.width, height: rect.height)
|
||||
super.select(withFrame: insetRect, in: controlView, editor: textObj, delegate: delegate, start: selStart, length: selLength)
|
||||
}
|
||||
|
||||
override func drawInterior(withFrame cellFrame: NSRect, in controlView: NSView) {
|
||||
let insetRect = NSRect(x: cellFrame.origin.x, y: cellFrame.origin.y + self.offset(), width: cellFrame.width, height: cellFrame.height)
|
||||
super.drawInterior(withFrame: insetRect, in: controlView)
|
||||
}
|
||||
}
|
||||
|
||||
/// MARK: - Utilities
|
||||
|
||||
fileprivate let kAccentColor: String = "AppleAccentColor"
|
||||
fileprivate extension NSColor {
|
||||
|
||||
/// The system accent color, with fallbacks for older macOS versions
|
||||
static var systemAccentColor: NSColor {
|
||||
if #available(OSX 10.14, *) {
|
||||
// macOS 10.14 and above have a dedicated static NSColor
|
||||
return NSColor.controlAccentColor
|
||||
}
|
||||
|
||||
// Use standard user defaults for anything lower than 10.14
|
||||
let userDefaults = UserDefaults.standard
|
||||
guard userDefaults.object(forKey: kAccentColor) != nil else {
|
||||
return DefaultColor()
|
||||
}
|
||||
|
||||
return ColorForSystemColorOffset(userDefaults.integer(forKey: kAccentColor))
|
||||
}
|
||||
|
||||
/// Map an integer value to a system color
|
||||
static func ColorForSystemColorOffset(_ value: Int) -> NSColor {
|
||||
switch value {
|
||||
case -1: return NSColor.systemGray
|
||||
case 0: return NSColor.systemRed
|
||||
case 1: return NSColor.systemOrange
|
||||
case 2: return NSColor.systemYellow
|
||||
case 3: return NSColor.systemGreen
|
||||
case 4: return NSColor.systemBlue
|
||||
case 5: return NSColor.systemPurple
|
||||
case 6: return NSColor.systemPink
|
||||
default: return DefaultColor()
|
||||
}
|
||||
}
|
||||
|
||||
static func DefaultColor() -> NSColor {
|
||||
if #available(OSX 11.0, *) {
|
||||
return NSColor.systemGray
|
||||
}
|
||||
else {
|
||||
return NSColor.systemBlue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
<?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>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(MARKETING_VERSION)</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2020 Darren Ford. All rights reserved.</string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,46 @@
|
|||
//
|
||||
// utils.swift
|
||||
//
|
||||
// Copyright © 2023 Darren Ford. All rights reserved.
|
||||
//
|
||||
// MIT license
|
||||
//
|
||||
// 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
|
||||
import AppKit
|
||||
|
||||
protocol DSFFloatLabelledTextFieldCellProtocol {
|
||||
var topOffset: CGFloat { get set }
|
||||
}
|
||||
|
||||
extension NSColor {
|
||||
/// A backwards compatible `controlAccentColor`
|
||||
@inlinable static var simulatedAccentColor: NSColor {
|
||||
if #available(macOS 10.14, *) {
|
||||
// macOS 10.14 and above have a dedicated static NSColor
|
||||
return NSColor.controlAccentColor
|
||||
}
|
||||
else {
|
||||
// Just use the menu highlight color - there's no concept of 'accent' color pre 10.14
|
||||
return NSColor.selectedMenuItemColor
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue