Skip to content

Commit 3ee9bfc

Browse files
committed
some doco
1 parent b085dbc commit 3ee9bfc

File tree

7 files changed

+117
-7
lines changed

7 files changed

+117
-7
lines changed

Demo/TextField Demo/TextField Demo.xcodeproj/project.pbxproj

+4-4
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@
221221
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
222222
GCC_WARN_UNUSED_FUNCTION = YES;
223223
GCC_WARN_UNUSED_VARIABLE = YES;
224-
MACOSX_DEPLOYMENT_TARGET = 12.3;
224+
MACOSX_DEPLOYMENT_TARGET = 10.11;
225225
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
226226
MTL_FAST_MATH = YES;
227227
ONLY_ACTIVE_ARCH = YES;
@@ -275,7 +275,7 @@
275275
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
276276
GCC_WARN_UNUSED_FUNCTION = YES;
277277
GCC_WARN_UNUSED_VARIABLE = YES;
278-
MACOSX_DEPLOYMENT_TARGET = 12.3;
278+
MACOSX_DEPLOYMENT_TARGET = 10.11;
279279
MTL_ENABLE_DEBUG_INFO = NO;
280280
MTL_FAST_MATH = YES;
281281
SDKROOT = macosx;
@@ -293,7 +293,7 @@
293293
CODE_SIGN_STYLE = Automatic;
294294
COMBINE_HIDPI_IMAGES = YES;
295295
CURRENT_PROJECT_VERSION = 1;
296-
DEVELOPMENT_TEAM = 3L6RK3LGGW;
296+
DEVELOPMENT_TEAM = "";
297297
ENABLE_HARDENED_RUNTIME = YES;
298298
GENERATE_INFOPLIST_FILE = YES;
299299
INFOPLIST_KEY_NSHumanReadableCopyright = "";
@@ -321,7 +321,7 @@
321321
CODE_SIGN_STYLE = Automatic;
322322
COMBINE_HIDPI_IMAGES = YES;
323323
CURRENT_PROJECT_VERSION = 1;
324-
DEVELOPMENT_TEAM = 3L6RK3LGGW;
324+
DEVELOPMENT_TEAM = "";
325325
ENABLE_HARDENED_RUNTIME = YES;
326326
GENERATE_INFOPLIST_FILE = YES;
327327
INFOPLIST_KEY_NSHumanReadableCopyright = "";

Demo/TextField Demo/TextField Demo/AppDelegate.swift

+5
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ class AppDelegate: NSObject, NSApplicationDelegate {
1515

1616
func applicationDidFinishLaunching(_ aNotification: Notification) {
1717
// Insert code here to initialize your application
18+
19+
let str = "a=🧖🏼‍♀️, b=💆‍♂️, c=🙆🏾"
20+
Swift.print(str.count)
21+
Swift.print(str.utf8.count)
22+
Swift.print(str.utf16.count)
1823
}
1924

2025
func applicationWillTerminate(_ aNotification: Notification) {

README.md

+105-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,107 @@
11
# DSFMaxLengthDisplayTextField
22

3-
A description of this package.
3+
<p align="center">
4+
<img src="https://img.shields.io/github/v/tag/dagronf/DSFMaxLengthDisplayTextField" />
5+
<img src="https://img.shields.io/badge/macOS-10.11+-red" />
6+
<img src="https://img.shields.io/badge/License-MIT-lightgrey" />
7+
<a href="https://swift.org/package-manager">
8+
<img src="https://img.shields.io/badge/spm-compatible-brightgreen.svg?style=flat" alt="Swift Package Manager" />
9+
</a>
10+
</p>
11+
<p align="center">
12+
13+
An `NSTextField` that specifies a maximum count after which text is highlighted to indicate an overflow
14+
15+
![animated demo](./screenshots/primary.gif)
16+
17+
![Multiline](./screenshots/secondary.png)
18+
19+
## Why?
20+
21+
I always liked the Twitter approach for indicating that text was oversized - it allows you to easily curate your content appropriately to fit the available size.
22+
23+
## API
24+
25+
This control uses the concept of a "grapheme cluster" for its character count - this means that emojis/complex characters represent a single character within the string
26+
27+
For example, the string `a=🧖🏼‍♀️, b=💆‍♂️, c=🙆🏾` represents 13 characters
28+
29+
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
30+
|----|----|----|----|----|----|----|----|----|----|----|----|----|
31+
| a | = | 🧖🏼‍♀️ | , | | b | = | 💆‍♂️ | , | | c | = | 🙆🏾 |
32+
33+
<!-- **Note:** In UTF8, this length is 48, UTF16 the length is 26 -->
34+
35+
### Settable properties
36+
37+
| Property | Type | Description |
38+
|-------------------------------|-----------|-------------------------------------------------------|
39+
| `maxCharacters` | `Int` | The maximum number of characters allowed |
40+
| `overflowTextColor` | `NSColor` | The color to use for 'overflow' characters |
41+
| `overflowTextBackgroundColor` | `NSColor` | The background color to use for 'overflow' characters |
42+
| `underlineOverflowCharacters` | `Bool` | Whether to underline overflow characters |
43+
44+
### Observable properties
45+
46+
These properties are KVO observable.
47+
48+
| Property | Type | Description |
49+
|-------------------------------|--------|-----------------------------------------------------------|
50+
| `isValid` | `Bool` | Does the text fit within the maximum characters specified |
51+
| `characterCount` | `Int` | Total character count |
52+
| `charactersAvailable` | `Int` | The number of characters available before overflow occurs |
53+
| `overflowCharacterCount` | `Int` | The number of overflow characters |
54+
55+
### Callbacks
56+
57+
| Parameter | Type | Description |
58+
|----------------------------|------------------|------------------------------------|
59+
| `contentChangedCallback` | `() -> Void` | Called when the content changes |
60+
| `isValidChangedCallback` | `(Bool) -> Void` | Called when the validity changes |
61+
62+
### Combine (macOS 10.15+)
63+
64+
| Parameter | Description |
65+
|----------------------|--------------------------------------------------|
66+
| `validityPublisher` | Publishes when the validity of the field changes |
67+
68+
<details>
69+
<summary>Combine Example Usage</summary>
70+
71+
```swift
72+
@IBOutlet weak var titleField: DSFMaxLengthDisplayTextField!
73+
...
74+
titleField.validityPublisher
75+
.removeDuplicates()
76+
.sink { newValue in
77+
Swift.print("Title Validity changed: \(newValue)")
78+
}
79+
```
80+
81+
</details>
82+
83+
## License
84+
85+
```
86+
MIT License
87+
88+
Copyright (c) 2022 Darren Ford
89+
90+
Permission is hereby granted, free of charge, to any person obtaining a copy
91+
of this software and associated documentation files (the "Software"), to deal
92+
in the Software without restriction, including without limitation the rights
93+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
94+
copies of the Software, and to permit persons to whom the Software is
95+
furnished to do so, subject to the following conditions:
96+
97+
The above copyright notice and this permission notice shall be included in all
98+
copies or substantial portions of the Software.
99+
100+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
101+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
102+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
103+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
104+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
105+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
106+
SOFTWARE.
107+
```

Sources/DSFMaxLengthDisplayTextField/DSFMaxLengthDisplayTextField.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ open class DSFMaxLengthDisplayTextField: NSTextField, VIViewCustomInvalidating {
4141

4242
// MARK: - Counting
4343

44-
/// The maximum number of grapheme clusters allowed in the field (eg. "🧖🏼‍♀️💆‍♂️🙆🏾abc" == 6)
44+
/// The maximum number of grapheme clusters allowed in the field (eg. "a=🧖🏼‍♀️, b=💆‍♂️, c=🙆🏾" == 13)
4545
@IBInspectable @VIViewInvalidating(.display)
4646
public dynamic var maxCharacters: Int = 20
4747

Sources/DSFMaxLengthDisplayTextField/private/DSFMaxLengthDisplayTextField+private.swift

+2-1
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,13 @@ internal extension DSFMaxLengthDisplayTextField {
5858
}
5959

6060
func update() {
61+
// Need to update the content on the main thread
6162
DispatchQueue.main.async { [weak self] in
6263
self?._update()
6364
}
6465
}
6566

66-
func _update() {
67+
private func _update() {
6768
let defaultTraits: [NSAttributedString.Key: Any] = [
6869
.font: self.font as Any,
6970
.foregroundColor: NSColor.textColor,

screenshots/primary.gif

137 KB
Loading

screenshots/secondary.png

52.7 KB
Loading

0 commit comments

Comments
 (0)