Skip to content

Commit 2c586a6

Browse files
committed
Add initial NSMutableAttributedString
1 parent 32ea959 commit 2c586a6

File tree

4 files changed

+115
-4
lines changed

4 files changed

+115
-4
lines changed

objc2-foundation/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
2222
* Added `NSUUID` object.
2323
* Added `NSMutableString` object.
2424
* Added basic `NSAttributedString` object.
25+
* Added basic `NSMutableAttributedString` object.
2526

2627
### Changed
2728
* **BREAKING**: Removed the following helper traits in favor of inherent

objc2-foundation/src/attributed_string.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ use objc2::msg_send;
44
use objc2::rc::{DefaultId, Id, Shared};
55
use objc2::runtime::Object;
66

7-
use crate::{NSCopying, NSDictionary, NSObject, NSString};
7+
use crate::{
8+
NSCopying, NSDictionary, NSMutableAttributedString, NSMutableCopying, NSObject, NSString,
9+
};
810

911
object! {
1012
/// A string that has associated attributes for portions of its text.
@@ -114,6 +116,10 @@ unsafe impl NSCopying for NSAttributedString {
114116
type Output = NSAttributedString;
115117
}
116118

119+
unsafe impl NSMutableCopying for NSAttributedString {
120+
type Output = NSMutableAttributedString;
121+
}
122+
117123
#[cfg(test)]
118124
mod tests {
119125
use alloc::string::ToString;
@@ -152,8 +158,8 @@ mod tests {
152158
// assert_eq!(s1.as_ptr(), s2.as_ptr());
153159
assert!(s2.is_kind_of(NSAttributedString::class()));
154160

155-
// let s3 = s1.mutable_copy();
156-
// assert_ne!(s1.as_ptr(), s3.as_ptr() as *mut NSAttributedString);
157-
// assert!(s3.is_kind_of(NSMutableAttributedString::class()));
161+
let s3 = s1.mutable_copy();
162+
assert_ne!(s1.as_ptr(), s3.as_ptr() as *mut NSAttributedString);
163+
assert!(s3.is_kind_of(NSMutableAttributedString::class()));
158164
}
159165
}

objc2-foundation/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ pub use self::copying::{NSCopying, NSMutableCopying};
4848
pub use self::data::{NSData, NSMutableData};
4949
pub use self::dictionary::NSDictionary;
5050
pub use self::enumerator::{NSEnumerator, NSFastEnumeration, NSFastEnumerator};
51+
pub use self::mutable_attributed_string::NSMutableAttributedString;
5152
pub use self::mutable_string::NSMutableString;
5253
pub use self::object::NSObject;
5354
pub use self::process_info::NSProcessInfo;
@@ -75,6 +76,7 @@ mod copying;
7576
mod data;
7677
mod dictionary;
7778
mod enumerator;
79+
mod mutable_attributed_string;
7880
mod mutable_string;
7981
mod object;
8082
mod process_info;
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
use core::ptr::NonNull;
2+
3+
use objc2::msg_send;
4+
use objc2::rc::{DefaultId, Id, Owned, Shared};
5+
6+
use crate::{NSAttributedString, NSCopying, NSMutableCopying, NSString};
7+
8+
object! {
9+
/// A mutable string that has associated attributes.
10+
///
11+
/// See [Apple's documentation](https://developer.apple.com/documentation/foundation/nsmutableattributedstring?language=objc).
12+
unsafe pub struct NSMutableAttributedString: NSAttributedString;
13+
}
14+
15+
// TODO: SAFETY
16+
unsafe impl Sync for NSMutableAttributedString {}
17+
unsafe impl Send for NSMutableAttributedString {}
18+
19+
/// Creating mutable attributed strings.
20+
impl NSMutableAttributedString {
21+
unsafe_def_fn! {
22+
/// Construct an empty mutable attributed string.
23+
pub fn new -> Owned;
24+
}
25+
26+
// TODO: new_with_attributes
27+
28+
#[doc(alias = "initWithString:")]
29+
pub fn from_nsstring(string: &NSString) -> Id<Self, Owned> {
30+
unsafe {
31+
let obj: *mut Self = msg_send![Self::class(), alloc];
32+
let obj: *mut Self = msg_send![obj, initWithString: string];
33+
Id::new(NonNull::new_unchecked(obj))
34+
}
35+
}
36+
37+
#[doc(alias = "initWithAttributedString:")]
38+
pub fn from_attributed_nsstring(attributed_string: &NSAttributedString) -> Id<Self, Owned> {
39+
unsafe {
40+
let obj: *mut Self = msg_send![Self::class(), alloc];
41+
let obj: *mut Self = msg_send![obj, initWithAttributedString: attributed_string];
42+
Id::new(NonNull::new_unchecked(obj))
43+
}
44+
}
45+
}
46+
47+
/// Modifying the attributed string.
48+
impl NSMutableAttributedString {
49+
// TODO
50+
// - mutableString
51+
// - replaceCharactersInRange:withString:
52+
// - setAttributes:range:
53+
54+
/// Replaces the entire attributed string.
55+
#[doc(alias = "setAttributedString:")]
56+
pub fn replace(&mut self, attributed_string: &NSAttributedString) {
57+
unsafe { msg_send![self, setAttributedString: attributed_string] }
58+
}
59+
}
60+
61+
impl DefaultId for NSMutableAttributedString {
62+
type Ownership = Owned;
63+
64+
#[inline]
65+
fn default_id() -> Id<Self, Self::Ownership> {
66+
Self::new()
67+
}
68+
}
69+
70+
unsafe impl NSCopying for NSMutableAttributedString {
71+
type Ownership = Shared;
72+
type Output = NSAttributedString;
73+
}
74+
75+
unsafe impl NSMutableCopying for NSMutableAttributedString {
76+
type Output = NSMutableAttributedString;
77+
}
78+
79+
#[cfg(test)]
80+
mod tests {
81+
use alloc::string::ToString;
82+
83+
use super::*;
84+
85+
#[test]
86+
fn test_new() {
87+
let s = NSAttributedString::new();
88+
assert_eq!(&s.string().to_string(), "");
89+
}
90+
91+
#[test]
92+
fn test_copy() {
93+
let s1 = NSMutableAttributedString::from_nsstring(&NSString::from_str("abc"));
94+
let s2 = s1.copy();
95+
assert_ne!(s1.as_ptr() as *const NSAttributedString, s2.as_ptr());
96+
assert!(s2.is_kind_of(NSAttributedString::class()));
97+
98+
let s3 = s1.mutable_copy();
99+
assert_ne!(s1.as_ptr(), s3.as_ptr());
100+
assert!(s3.is_kind_of(NSMutableAttributedString::class()));
101+
}
102+
}

0 commit comments

Comments
 (0)