Small refactor and cleanup, added SPM support

This commit is contained in:
Darren Ford 2020-01-02 08:53:33 +11:00
parent 603d851619
commit 69fa2990c7
13 changed files with 188 additions and 123 deletions

2
.gitignore vendored
View File

@ -1 +1,3 @@
DSFFloatLabelledTextControls.xcodeproj/xcuserdata
xcschememanagement.plist
.swiftpm

View File

@ -8,8 +8,8 @@
/* Begin PBXBuildFile section */
2351F84F2207D15C00EFA4F7 /* DSFFloatLabelledTextControl.h in Headers */ = {isa = PBXBuildFile; fileRef = 2351F84D2207D15C00EFA4F7 /* DSFFloatLabelledTextControl.h */; settings = {ATTRIBUTES = (Public, ); }; };
2351F8522207D15C00EFA4F7 /* DSFFloatLabelledTextControl.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2351F84B2207D15C00EFA4F7 /* DSFFloatLabelledTextControl.framework */; };
2351F8532207D15C00EFA4F7 /* DSFFloatLabelledTextControl.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 2351F84B2207D15C00EFA4F7 /* DSFFloatLabelledTextControl.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
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 */; };
@ -35,7 +35,7 @@
dstPath = "";
dstSubfolderSpec = 10;
files = (
2351F8532207D15C00EFA4F7 /* DSFFloatLabelledTextControl.framework in Embed Frameworks */,
2351F8532207D15C00EFA4F7 /* DSFFloatLabelledTextField.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
@ -43,7 +43,7 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
2351F84B2207D15C00EFA4F7 /* DSFFloatLabelledTextControl.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DSFFloatLabelledTextControl.framework; sourceTree = BUILT_PRODUCTS_DIR; };
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>"; };
@ -56,6 +56,7 @@
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>"; };
23FFF1CD23BD490F008FA55A /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -70,31 +71,32 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
2351F8522207D15C00EFA4F7 /* DSFFloatLabelledTextControl.framework in Frameworks */,
2351F8522207D15C00EFA4F7 /* DSFFloatLabelledTextField.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
2351F84C2207D15C00EFA4F7 /* DSFFloatLabelledTextControl */ = {
2351F84C2207D15C00EFA4F7 /* DSFFloatLabelledTextField */ = {
isa = PBXGroup;
children = (
23A2B7FA2207931500B2FC77 /* DSFFloatLabelledTextField.swift */,
2351F84D2207D15C00EFA4F7 /* DSFFloatLabelledTextControl.h */,
2351F84E2207D15C00EFA4F7 /* Info.plist */,
);
path = DSFFloatLabelledTextControl;
path = DSFFloatLabelledTextField;
sourceTree = "<group>";
};
23A2B7E0220792FE00B2FC77 = {
isa = PBXGroup;
children = (
23FFF1CF23BD4982008FA55A /* Demos */,
23FFF1CE23BD496A008FA55A /* Sources */,
23ACF96D228A3F6600FF6594 /* DSFFloatLabelledTextControl.podspec */,
2351F85922082AD800EFA4F7 /* LICENSE */,
2351F85A22082AD800EFA4F7 /* README.md */,
23A2B7EB220792FE00B2FC77 /* DSFFloatLabelledTextControls */,
2351F84C2207D15C00EFA4F7 /* DSFFloatLabelledTextControl */,
23FFF1CD23BD490F008FA55A /* Package.swift */,
23A2B7EA220792FE00B2FC77 /* Products */,
);
sourceTree = "<group>";
@ -103,7 +105,7 @@
isa = PBXGroup;
children = (
23A2B7E9220792FE00B2FC77 /* DSFFloatLabelledTextControls.app */,
2351F84B2207D15C00EFA4F7 /* DSFFloatLabelledTextControl.framework */,
2351F84B2207D15C00EFA4F7 /* DSFFloatLabelledTextField.framework */,
);
name = Products;
sourceTree = "<group>";
@ -120,6 +122,22 @@
path = DSFFloatLabelledTextControls;
sourceTree = "<group>";
};
23FFF1CE23BD496A008FA55A /* Sources */ = {
isa = PBXGroup;
children = (
2351F84C2207D15C00EFA4F7 /* DSFFloatLabelledTextField */,
);
path = Sources;
sourceTree = "<group>";
};
23FFF1CF23BD4982008FA55A /* Demos */ = {
isa = PBXGroup;
children = (
23A2B7EB220792FE00B2FC77 /* DSFFloatLabelledTextControls */,
);
path = Demos;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
@ -134,9 +152,9 @@
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
2351F84A2207D15C00EFA4F7 /* DSFFloatLabelledTextControl */ = {
2351F84A2207D15C00EFA4F7 /* DSFFloatLabelledTextField */ = {
isa = PBXNativeTarget;
buildConfigurationList = 2351F8542207D15C00EFA4F7 /* Build configuration list for PBXNativeTarget "DSFFloatLabelledTextControl" */;
buildConfigurationList = 2351F8542207D15C00EFA4F7 /* Build configuration list for PBXNativeTarget "DSFFloatLabelledTextField" */;
buildPhases = (
2351F8462207D15C00EFA4F7 /* Headers */,
2351F8472207D15C00EFA4F7 /* Sources */,
@ -147,9 +165,9 @@
);
dependencies = (
);
name = DSFFloatLabelledTextControl;
name = DSFFloatLabelledTextField;
productName = DSFFloatLabelledTextControl;
productReference = 2351F84B2207D15C00EFA4F7 /* DSFFloatLabelledTextControl.framework */;
productReference = 2351F84B2207D15C00EFA4F7 /* DSFFloatLabelledTextField.framework */;
productType = "com.apple.product-type.framework";
};
23A2B7E8220792FE00B2FC77 /* DSFFloatLabelledTextControls */ = {
@ -203,7 +221,7 @@
projectRoot = "";
targets = (
23A2B7E8220792FE00B2FC77 /* DSFFloatLabelledTextControls */,
2351F84A2207D15C00EFA4F7 /* DSFFloatLabelledTextControl */,
2351F84A2207D15C00EFA4F7 /* DSFFloatLabelledTextField */,
);
};
/* End PBXProject section */
@ -251,7 +269,7 @@
/* Begin PBXTargetDependency section */
2351F8512207D15C00EFA4F7 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 2351F84A2207D15C00EFA4F7 /* DSFFloatLabelledTextControl */;
target = 2351F84A2207D15C00EFA4F7 /* DSFFloatLabelledTextField */;
targetProxy = 2351F8502207D15C00EFA4F7 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
@ -271,7 +289,7 @@
2351F8552207D15C00EFA4F7 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_IDENTITY = "";
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
@ -281,7 +299,7 @@
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = DSFFloatLabelledTextControl/Info.plist;
INFOPLIST_FILE = Sources/DSFFloatLabelledTextField/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
@ -300,7 +318,7 @@
2351F8562207D15C00EFA4F7 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_IDENTITY = "";
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
@ -310,7 +328,7 @@
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = DSFFloatLabelledTextControl/Info.plist;
INFOPLIST_FILE = Sources/DSFFloatLabelledTextField/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
@ -447,16 +465,18 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = DSFFloatLabelledTextControls/DSFFloatLabelledTextControls.entitlements;
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = 3L6RK3LGGW;
INFOPLIST_FILE = DSFFloatLabelledTextControls/Info.plist;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = Demos/DSFFloatLabelledTextControls/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.darrenford.DSFFloatLabelledTextControls;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_VERSION = 5.0;
};
name = Debug;
@ -467,16 +487,18 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = DSFFloatLabelledTextControls/DSFFloatLabelledTextControls.entitlements;
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = 3L6RK3LGGW;
INFOPLIST_FILE = DSFFloatLabelledTextControls/Info.plist;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = Demos/DSFFloatLabelledTextControls/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.darrenford.DSFFloatLabelledTextControls;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_VERSION = 5.0;
};
name = Release;
@ -484,7 +506,7 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
2351F8542207D15C00EFA4F7 /* Build configuration list for PBXNativeTarget "DSFFloatLabelledTextControl" */ = {
2351F8542207D15C00EFA4F7 /* Build configuration list for PBXNativeTarget "DSFFloatLabelledTextField" */ = {
isa = XCConfigurationList;
buildConfigurations = (
2351F8552207D15C00EFA4F7 /* Debug */,

View File

@ -27,7 +27,7 @@
import Cocoa
import DSFFloatLabelledTextControl
import DSFFloatLabelledTextField
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="15702" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14490.70"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15702"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
@ -679,24 +679,25 @@
</menu>
</menuItem>
</items>
<point key="canvasLocation" x="139" y="154"/>
</menu>
<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="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
<view key="contentView" wantsLayer="YES" id="EiT-Mj-1SZ">
<rect key="frame" x="0.0" y="0.0" width="497" height="468"/>
<view key="contentView" wantsLayer="YES" misplaced="YES" id="EiT-Mj-1SZ">
<rect key="frame" x="0.0" y="0.0" width="497" height="441"/>
<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="307" width="463" height="143"/>
<rect key="frame" x="17" y="303" width="463" height="140"/>
<view key="contentView" id="fUJ-lp-O9s">
<rect key="frame" x="3" y="3" width="457" height="137"/>
<rect key="frame" x="3" y="3" width="457" 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="DSFFloatLabelledTextControl">
<rect key="frame" x="12" y="99" width="433" height="26"/>
<textField horizontalHuggingPriority="50" verticalHuggingPriority="750" horizontalCompressionResistancePriority="500" verticalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="tnz-85-NdV" userLabel="Title Field" customClass="DSFFloatLabelledTextField" customModule="DSFFloatLabelledTextField">
<rect key="frame" x="12" y="97" width="433" height="25"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="border" alignment="left" title="This is a fusdfjk" placeholderString="Title" id="ETD-Tb-a7N">
<font key="font" metaFont="system" size="18"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
@ -709,10 +710,10 @@
</userDefinedRuntimeAttributes>
</textField>
<box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="pyP-dk-pAy">
<rect key="frame" x="12" y="88" width="433" height="5"/>
<rect key="frame" x="12" y="86" width="433" height="5"/>
</box>
<textField horizontalHuggingPriority="50" verticalHuggingPriority="750" horizontalCompressionResistancePriority="500" verticalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="zbB-HI-AVu" userLabel="Price Field" customClass="DSFFloatLabelledTextField" customModule="DSFFloatLabelledTextControl">
<rect key="frame" x="12" y="56" width="100" height="26"/>
<textField horizontalHuggingPriority="50" verticalHuggingPriority="750" horizontalCompressionResistancePriority="500" verticalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="zbB-HI-AVu" userLabel="Price Field" customClass="DSFFloatLabelledTextField" customModule="DSFFloatLabelledTextField">
<rect key="frame" x="12" y="55" width="100" height="25"/>
<constraints>
<constraint firstAttribute="width" constant="100" id="Dhv-LX-D4R"/>
</constraints>
@ -728,10 +729,10 @@
</userDefinedRuntimeAttributes>
</textField>
<box horizontalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="Mrp-MT-gGa">
<rect key="frame" x="117" y="47" width="5" height="44"/>
<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="DSFFloatLabelledTextControl">
<rect key="frame" x="128" y="56" width="317" height="26"/>
<textField horizontalHuggingPriority="50" verticalHuggingPriority="750" horizontalCompressionResistancePriority="500" verticalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="SAo-aL-Ofe" userLabel="Location Field" customClass="DSFFloatLabelledTextField" customModule="DSFFloatLabelledTextField">
<rect key="frame" x="128" y="55" width="317" height="25"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="border" alignment="left" placeholderString="Specific Location (Optional)" id="BHQ-MA-tIJ">
<font key="font" metaFont="system" size="18"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
@ -744,10 +745,10 @@
</userDefinedRuntimeAttributes>
</textField>
<box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="YiQ-45-hxx">
<rect key="frame" x="12" y="45" width="433" height="5"/>
<rect key="frame" x="12" y="44" width="433" height="5"/>
</box>
<textField horizontalHuggingPriority="50" verticalHuggingPriority="750" horizontalCompressionResistancePriority="500" translatesAutoresizingMaskIntoConstraints="NO" id="h8z-Ku-xLD" customClass="DSFFloatLabelledTextField" customModule="DSFFloatLabelledTextControl">
<rect key="frame" x="12" y="13" width="433" height="26"/>
<textField horizontalHuggingPriority="50" verticalHuggingPriority="750" horizontalCompressionResistancePriority="500" translatesAutoresizingMaskIntoConstraints="NO" id="h8z-Ku-xLD" customClass="DSFFloatLabelledTextField" customModule="DSFFloatLabelledTextField">
<rect key="frame" x="12" y="13" width="433" height="25"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="border" alignment="left" placeholderString="Description" id="XtC-Dr-5RL">
<font key="font" metaFont="system" size="18"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
@ -786,13 +787,13 @@
</view>
</box>
<box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="CVr-p8-VOx">
<rect key="frame" x="20" y="277" width="457" height="5"/>
<rect key="frame" x="20" y="273" 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="215" width="457" height="34"/>
<rect key="frame" x="20" y="212" 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="DSFFloatLabelledTextControl">
<rect key="frame" x="0.0" y="0.0" width="50" height="34"/>
<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"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" alignment="left" placeholderString="First Name" drawsBackground="YES" id="5Wb-1R-5YV">
<font key="font" metaFont="system" size="24"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
@ -804,8 +805,8 @@
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</textField>
<textField horizontalHuggingPriority="50" verticalHuggingPriority="750" horizontalCompressionResistancePriority="500" verticalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="fQG-V9-3hv" userLabel="Title Field" customClass="DSFFloatLabelledTextField" customModule="DSFFloatLabelledTextControl">
<rect key="frame" x="58" y="0.0" width="399" height="34"/>
<textField horizontalHuggingPriority="50" verticalHuggingPriority="750" horizontalCompressionResistancePriority="500" verticalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="fQG-V9-3hv" userLabel="Title Field" customClass="DSFFloatLabelledTextField" customModule="DSFFloatLabelledTextField">
<rect key="frame" x="58" y="0.0" width="399" height="33"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" alignment="left" placeholderString="Last Name" drawsBackground="YES" id="74P-hN-0Vg">
<font key="font" metaFont="system" size="24"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
@ -828,13 +829,13 @@
</customSpacing>
</stackView>
<box verticalHuggingPriority="750" boxType="separator" translatesAutoresizingMaskIntoConstraints="NO" id="QuB-jf-wmu">
<rect key="frame" x="20" y="179" width="457" height="5"/>
<rect key="frame" x="20" y="176" 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="85"/>
<rect key="frame" x="20" y="80" width="250" height="82"/>
<subviews>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="3hp-BV-Ls3" customClass="DSFFloatLabelledTextField" customModule="DSFFloatLabelledTextControl">
<rect key="frame" x="0.0" y="62" width="250" height="23"/>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="3hp-BV-Ls3" customClass="DSFFloatLabelledTextField" 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" placeholderString="Licensee Name" drawsBackground="YES" id="I01-Tl-E8r">
<font key="font" metaFont="system" size="14"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
@ -846,8 +847,8 @@
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</textField>
<textField horizontalHuggingPriority="100" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="MfQ-T7-eym" customClass="DSFFloatLabelledTextField" customModule="DSFFloatLabelledTextControl">
<rect key="frame" x="0.0" y="31" width="250" height="23"/>
<textField horizontalHuggingPriority="100" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="MfQ-T7-eym" customClass="DSFFloatLabelledTextField" customModule="DSFFloatLabelledTextField">
<rect key="frame" x="0.0" y="30" width="250" height="22"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" placeholderString="Serial Number" drawsBackground="YES" id="3Xv-o0-6Io">
<font key="font" metaFont="system" size="14"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
@ -859,8 +860,8 @@
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</textField>
<textField horizontalHuggingPriority="100" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ueu-5M-hVI" customClass="DSFFloatLabelledTextField" customModule="DSFFloatLabelledTextControl">
<rect key="frame" x="0.0" y="0.0" width="250" height="23"/>
<textField horizontalHuggingPriority="100" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ueu-5M-hVI" customClass="DSFFloatLabelledTextField" customModule="DSFFloatLabelledTextField">
<rect key="frame" x="0.0" y="0.0" width="250" height="22"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" placeholderString="Maximum Clients" drawsBackground="YES" id="l0d-Jv-tQ6">
<font key="font" metaFont="system" size="14"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>

29
Package.swift Normal file
View File

@ -0,0 +1,29 @@
// swift-tools-version:5.1
// The swift-tools-version declares the minimum version of Swift required to build this package.
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]
)

View File

@ -2,6 +2,11 @@
A macOS Cocoa single-line NSTextField that implements the Float Label Pattern. You can read about the float pattern [here](http://mds.is/float-label-pattern/)
![](https://img.shields.io/github/v/tag/dagronf/DSFFloatLabelledTextControl) ![](https://img.shields.io/badge/macOS-10.11+-red) ![](https://img.shields.io/badge/Swift-5.0-orange.svg)
![](https://img.shields.io/badge/License-MIT-lightgrey) [![](https://img.shields.io/badge/pod-compatible-informational)](https://cocoapods.org) [![](https://img.shields.io/badge/spm-compatible-brightgreen.svg?style=flat)](https://swift.org/package-manager)
## Screenshot
![](https://github.com/dagronf/dagronf.github.io/raw/master/art/projects/DSFFloatingLabel/floating_label_text_field.gif)
## Why?
@ -53,6 +58,7 @@ func changeFonts()
## License
```
MIT License
Copyright (c) 2019 Darren Ford
@ -74,3 +80,4 @@ 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.
```

View File

@ -27,33 +27,6 @@
import Cocoa
class DSFFloatLabelledTextFieldCell: NSTextFieldCell {
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)
}
}
@IBDesignable open class DSFFloatLabelledTextField: NSTextField {
@IBInspectable public var placeholderTextSize: CGFloat = 10 {
didSet {
@ -78,6 +51,38 @@ class DSFFloatLabelledTextFieldCell: NSTextFieldCell {
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.placeholderHeight
}
/// Returns of the color for the floating text
private var floatTextColor: NSColor {
if #available(macOS 10.14, *) {
return NSColor.controlAccentColor
}
else {
return NSColor.headerTextColor
}
}
/// Return the cell as a float cell type
private var fieldCell: DSFFloatLabelledTextFieldCell {
return self.cell as! DSFFloatLabelledTextFieldCell
}
/// Set the fonts to be used in the control
open func setFonts(primary: NSFont, secondary: NSFont) {
self.floatingLabel.font = secondary
@ -100,15 +105,6 @@ class DSFFloatLabelledTextFieldCell: NSTextFieldCell {
}
}
private func floatTextColor() -> NSColor {
if #available(macOS 10.14, *) {
return NSColor.controlAccentColor
}
else {
return NSColor.headerTextColor
}
}
/// Build the floating label
private func createFloatingLabel() {
if self.floatingLabel.superview == nil {
@ -123,7 +119,7 @@ class DSFFloatLabelledTextFieldCell: NSTextFieldCell {
self.floatingLabel.isBordered = false
self.floatingLabel.translatesAutoresizingMaskIntoConstraints = false
self.floatingLabel.font = NSFont.systemFont(ofSize: self.placeholderTextSize)
self.floatingLabel.textColor = self.floatTextColor()
self.floatingLabel.textColor = self.floatTextColor
self.floatingLabel.stringValue = self.placeholderString ?? ""
self.floatingLabel.alphaValue = 0.0
self.floatingLabel.alignment = self.alignment
@ -157,7 +153,7 @@ class DSFFloatLabelledTextFieldCell: NSTextFieldCell {
/// Build the text field's custom cell
private func createCustomCell() {
let customCell = DSFFloatLabelledTextFieldCell()
customCell.topOffset = self.placeholderHeight()
customCell.topOffset = self.placeholderHeight
customCell.isEditable = true
customCell.wraps = false
@ -189,7 +185,7 @@ class DSFFloatLabelledTextFieldCell: NSTextFieldCell {
item: self, attribute: .height,
relatedBy: .equal,
toItem: nil, attribute: .notAnAttribute,
multiplier: 1.0, constant: self.controlHeight()
multiplier: 1.0, constant: self.controlHeight
)
self.addConstraint(self.heightConstraint!)
@ -199,30 +195,13 @@ class DSFFloatLabelledTextFieldCell: NSTextFieldCell {
}
}
/// Returns the height of the placeholder text
private func placeholderHeight() -> CGFloat {
let layoutManager = NSLayoutManager()
return layoutManager.defaultLineHeight(for: self.floatingLabel.font!) + 1
}
/// Returns the height of the primary (editable) text
private func textHeight() -> CGFloat {
let layoutManager = NSLayoutManager()
return layoutManager.defaultLineHeight(for: self.font!) + 1
}
/// Returns the total height of the control given the font settings
private func controlHeight() -> CGFloat {
return self.textHeight() + self.placeholderHeight()
}
/// 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.fieldCell().topOffset = self.placeholderHeight()
self.fieldCell.topOffset = self.placeholderHeight
self.expandFrame()
self.needsLayout = true
@ -230,8 +209,8 @@ class DSFFloatLabelledTextFieldCell: NSTextFieldCell {
/// Rebuild the frame of the text field to match the new settings
private func expandFrame() {
self.heightConstraint?.constant = self.controlHeight()
self.fieldCell().topOffset = self.placeholderHeight()
self.heightConstraint?.constant = self.controlHeight
self.fieldCell.topOffset = self.placeholderHeight
}
}
@ -260,7 +239,7 @@ extension DSFFloatLabelledTextField: NSTextFieldDelegate {
// '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
self?.floatingLabel.textColor = self?.floatTextColor()
self?.floatingLabel.textColor = self?.floatTextColor
}
}
return becomeResult
@ -271,11 +250,6 @@ extension DSFFloatLabelledTextField: NSTextFieldDelegate {
self.floatingLabel.textColor = NSColor.secondaryLabelColor
}
/// Helper function to get the current cell as the custom cell type
private func fieldCell() -> DSFFloatLabelledTextFieldCell {
return self.cell as! DSFFloatLabelledTextFieldCell
}
/// Does our text field currently have input focus?
private func isCurrentFocus() -> Bool {
// 1. Get the window's first responder
@ -311,7 +285,7 @@ extension DSFFloatLabelledTextField {
NSAnimationContext.runAnimationGroup({ context in
context.allowsImplicitAnimation = true
context.duration = 0.4
self.floatingTop?.constant = self.textHeight() / 1.5
self.floatingTop?.constant = self.textHeight / 1.5
self.floatingLabel.alphaValue = 0.0
self.layoutSubtreeIfNeeded()
}, completionHandler: {
@ -319,3 +293,33 @@ extension DSFFloatLabelledTextField {
})
}
}
// MARK: - Cell definition
private class DSFFloatLabelledTextFieldCell: NSTextFieldCell {
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)
}
}