Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
Material
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Dmitriy Stepanets
Material
Commits
c693872f
Unverified
Commit
c693872f
authored
Nov 04, 2016
by
Daniel Dahan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
editor: reworked TextStorage and Text into Editor
parent
b55650de
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
304 additions
and
296 deletions
+304
-296
Material.xcodeproj/project.pbxproj
+28
-6
Sources/iOS/CharacterAttribute.swift
+143
-0
Sources/iOS/Editor.swift
+79
-138
Sources/iOS/Text.swift
+0
-132
Sources/iOS/TextStorage.swift
+54
-20
No files found.
Material.xcodeproj/project.pbxproj
View file @
c693872f
...
...
@@ -7,6 +7,19 @@
objects
=
{
/* Begin PBXBuildFile section */
961276631DCD8B1800A7D920
/* CharacterAttribute.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
961276621DCD8B1800A7D920
/* CharacterAttribute.swift */
;
};
961276641DCD8CF200A7D920
/* PresenterCard.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
9631A7C01D95E3AC00CFB109
/* PresenterCard.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
961276651DCD8CF200A7D920
/* Capture.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96717B0D1DBE6AF600DA84DB
/* Capture.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
961276661DCD8CF200A7D920
/* CapturePreview.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96717B0F1DBE6AF600DA84DB
/* CapturePreview.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
961276671DCD8CF200A7D920
/* CaptureController.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96717B0E1DBE6AF600DA84DB
/* CaptureController.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
961276681DCD8CF200A7D920
/* Editor.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
961DED451DCC40C500F425B6
/* Editor.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
961276691DCD8CF200A7D920
/* EditorController.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
961DED4A1DCC546100F425B6
/* EditorController.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
9612766A1DCD8CF200A7D920
/* HeightPreset.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
9626CB9A1DAD3D1D003E2611
/* HeightPreset.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
9612766B1DCD8CF200A7D920
/* PhotoLibrary.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96717B161DBE6B1800DA84DB
/* PhotoLibrary.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
9612766C1DCD8CF200A7D920
/* PhotoLibraryController.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96717B171DBE6B1800DA84DB
/* PhotoLibraryController.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
9612766D1DCD8CF200A7D920
/* Pulse.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
9631A7C61D95E5D900CFB109
/* Pulse.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
9612766E1DCD8CF200A7D920
/* Display.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
9626CA961DAB53A8003E2611
/* Display.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
9612766F1DCD8CF200A7D920
/* CharacterAttribute.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
961276621DCD8B1800A7D920
/* CharacterAttribute.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
961DED461DCC40C500F425B6
/* Editor.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
961DED451DCC40C500F425B6
/* Editor.swift */
;
};
961DED4B1DCC546100F425B6
/* EditorController.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
961DED4A1DCC546100F425B6
/* EditorController.swift */
;
};
961EFC581D738FF600E84652
/* SnackbarController.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
961EFC571D738FF600E84652
/* SnackbarController.swift */
;
};
...
...
@@ -99,7 +112,6 @@
96BCB7E11CB40DC500C806FE
/* Bar.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB7981CB40DC500C806FE
/* Bar.swift */
;
};
96BCB7E21CB40DC500C806FE
/* RootController.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB7991CB40DC500C806FE
/* RootController.swift */
;
};
96BCB7E31CB40DC500C806FE
/* TabBar.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB79A1CB40DC500C806FE
/* TabBar.swift */
;
};
96BCB7E41CB40DC500C806FE
/* Text.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB79B1CB40DC500C806FE
/* Text.swift */
;
};
96BCB7E51CB40DC500C806FE
/* TextField.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB79C1CB40DC500C806FE
/* TextField.swift */
;
};
96BCB7E61CB40DC500C806FE
/* TextStorage.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB79D1CB40DC500C806FE
/* TextStorage.swift */
;
};
96BCB7E71CB40DC500C806FE
/* TextView.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB79E1CB40DC500C806FE
/* TextView.swift */
;
};
...
...
@@ -159,7 +171,6 @@
96BCB8461CB4115200C806FE
/* NavigationBar.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB7901CB40DC500C806FE
/* NavigationBar.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
96BCB8471CB4115200C806FE
/* NavigationController.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB7911CB40DC500C806FE
/* NavigationController.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
96BCB8481CB4115200C806FE
/* NavigationItem.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB7921CB40DC500C806FE
/* NavigationItem.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
96BCB8491CB4115200C806FE
/* Text.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB79B1CB40DC500C806FE
/* Text.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
96BCB84A1CB4115200C806FE
/* TextField.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB79C1CB40DC500C806FE
/* TextField.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
96BCB84B1CB4115200C806FE
/* TextStorage.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB79D1CB40DC500C806FE
/* TextStorage.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
96BCB84C1CB4115200C806FE
/* TextView.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB79E1CB40DC500C806FE
/* TextView.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
...
...
@@ -205,6 +216,7 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
961276621DCD8B1800A7D920
/* CharacterAttribute.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
CharacterAttribute.swift
;
sourceTree
=
"<group>"
;
};
961DED451DCC40C500F425B6
/* Editor.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
Editor.swift
;
sourceTree
=
"<group>"
;
};
961DED4A1DCC546100F425B6
/* EditorController.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
EditorController.swift
;
sourceTree
=
"<group>"
;
};
961EFC571D738FF600E84652
/* SnackbarController.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
SnackbarController.swift
;
sourceTree
=
"<group>"
;
};
...
...
@@ -288,7 +300,6 @@
96BCB7981CB40DC500C806FE
/* Bar.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
Bar.swift
;
sourceTree
=
"<group>"
;
};
96BCB7991CB40DC500C806FE
/* RootController.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
RootController.swift
;
sourceTree
=
"<group>"
;
};
96BCB79A1CB40DC500C806FE
/* TabBar.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
TabBar.swift
;
sourceTree
=
"<group>"
;
};
96BCB79B1CB40DC500C806FE
/* Text.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
Text.swift
;
sourceTree
=
"<group>"
;
};
96BCB79C1CB40DC500C806FE
/* TextField.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
TextField.swift
;
sourceTree
=
"<group>"
;
};
96BCB79D1CB40DC500C806FE
/* TextStorage.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
TextStorage.swift
;
sourceTree
=
"<group>"
;
};
96BCB79E1CB40DC500C806FE
/* TextView.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
TextView.swift
;
sourceTree
=
"<group>"
;
};
...
...
@@ -772,7 +783,7 @@
96BCB80E1CB4110E00C806FE
/* TextView */
=
{
isa
=
PBXGroup
;
children
=
(
96
BCB79B1CB40DC500C806FE
/* Text
.swift */
,
96
1276621DCD8B1800A7D920
/* CharacterAttribute
.swift */
,
96BCB79D1CB40DC500C806FE
/* TextStorage.swift */
,
96BCB79E1CB40DC500C806FE
/* TextView.swift */
,
);
...
...
@@ -845,7 +856,6 @@
96BCB8461CB4115200C806FE
/* NavigationBar.swift in Headers */
,
96BCB8471CB4115200C806FE
/* NavigationController.swift in Headers */
,
96BCB8481CB4115200C806FE
/* NavigationItem.swift in Headers */
,
96BCB8491CB4115200C806FE
/* Text.swift in Headers */
,
96BCB84A1CB4115200C806FE
/* TextField.swift in Headers */
,
96BCB84B1CB4115200C806FE
/* TextStorage.swift in Headers */
,
96BCB84C1CB4115200C806FE
/* TextView.swift in Headers */
,
...
...
@@ -875,6 +885,18 @@
9697F7C61D8F2573004741EC
/* PageTabBarController.swift in Headers */
,
9697F7CB1D8F2573004741EC
/* Snackbar.swift in Headers */
,
9697F7CC1D8F2573004741EC
/* SnackbarController.swift in Headers */
,
961276641DCD8CF200A7D920
/* PresenterCard.swift in Headers */
,
961276651DCD8CF200A7D920
/* Capture.swift in Headers */
,
961276661DCD8CF200A7D920
/* CapturePreview.swift in Headers */
,
961276671DCD8CF200A7D920
/* CaptureController.swift in Headers */
,
961276681DCD8CF200A7D920
/* Editor.swift in Headers */
,
961276691DCD8CF200A7D920
/* EditorController.swift in Headers */
,
9612766A1DCD8CF200A7D920
/* HeightPreset.swift in Headers */
,
9612766B1DCD8CF200A7D920
/* PhotoLibrary.swift in Headers */
,
9612766C1DCD8CF200A7D920
/* PhotoLibraryController.swift in Headers */
,
9612766D1DCD8CF200A7D920
/* Pulse.swift in Headers */
,
9612766E1DCD8CF200A7D920
/* Display.swift in Headers */
,
9612766F1DCD8CF200A7D920
/* CharacterAttribute.swift in Headers */
,
);
runOnlyForDeploymentPostprocessing
=
0
;
};
...
...
@@ -1143,9 +1165,9 @@
96BCB7CD1CB40DC500C806FE
/* PulseView.swift in Sources */
,
96BCB7DA1CB40DC500C806FE
/* NavigationController.swift in Sources */
,
96BCB7A81CB40DC500C806FE
/* FabButton.swift in Sources */
,
96BCB7E41CB40DC500C806FE
/* Text.swift in Sources */
,
96717B121DBE6AF600DA84DB
/* CaptureController.swift in Sources */
,
96717B181DBE6B1800DA84DB
/* PhotoLibrary.swift in Sources */
,
961276631DCD8B1800A7D920
/* CharacterAttribute.swift in Sources */
,
96BCB7AB1CB40DC500C806FE
/* ImageCard.swift in Sources */
,
96BCB7CB1CB40DC500C806FE
/* PulseAnimation.swift in Sources */
,
96BCB7AE1CB40DC500C806FE
/* Material+UIFont.swift in Sources */
,
...
...
Sources/iOS/CharacterAttribute.swift
0 → 100644
View file @
c693872f
/*
* Copyright (C) 2015 - 2016, Daniel Dahan and CosmicMind, Inc. <http://cosmicmind.com>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of CosmicMind nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import
UIKit
public
enum
CharacterAttribute
:
String
{
case
font
=
"NSFontAttributeName"
case
paragraphStyle
=
"NSParagraphStyleAttributeName"
case
forgroundColor
=
"NSForegroundColorAttributeName"
case
backgroundColor
=
"NSBackgroundColorAttributeName"
case
ligature
=
"NSLigatureAttributeName"
case
kern
=
"NSKernAttributeName"
case
strikethroughStyle
=
"NSStrikethroughStyleAttributeName"
case
underlineStyle
=
"NSUnderlineStyleAttributeName"
case
strokeColor
=
"NSStrokeColorAttributeName"
case
strokeWidth
=
"NSStrokeWidthAttributeName"
case
shadow
=
"NSShadowAttributeName"
case
textEffect
=
"NSTextEffectAttributeName"
case
attachment
=
"NSAttachmentAttributeName"
case
link
=
"NSLinkAttributeName"
case
baselineOffset
=
"NSBaselineOffsetAttributeName"
case
underlineColor
=
"NSUnderlineColorAttributeName"
case
strikethroughColor
=
"NSStrikethroughColorAttributeName"
case
obliqueness
=
"NSObliquenessAttributeName"
case
expansion
=
"NSExpansionAttributeName"
case
writingDirection
=
"NSWritingDirectionAttributeName"
case
verticalGlyphForm
=
"NSVerticalGlyphFormAttributeName"
}
public
func
CharacterAttributeToValue
(
attribute
:
CharacterAttribute
)
->
String
{
switch
attribute
{
case
.
font
:
return
NSFontAttributeName
case
.
paragraphStyle
:
return
NSParagraphStyleAttributeName
case
.
forgroundColor
:
return
NSForegroundColorAttributeName
case
.
backgroundColor
:
return
NSBackgroundColorAttributeName
case
.
ligature
:
return
NSLigatureAttributeName
case
.
kern
:
return
NSKernAttributeName
case
.
strikethroughStyle
:
return
NSStrikethroughStyleAttributeName
case
.
underlineStyle
:
return
NSUnderlineStyleAttributeName
case
.
strokeColor
:
return
NSStrokeColorAttributeName
case
.
strokeWidth
:
return
NSStrokeWidthAttributeName
case
.
shadow
:
return
NSShadowAttributeName
case
.
textEffect
:
return
NSTextEffectAttributeName
case
.
attachment
:
return
NSAttachmentAttributeName
case
.
link
:
return
NSLinkAttributeName
case
.
baselineOffset
:
return
NSBaselineOffsetAttributeName
case
.
underlineColor
:
return
NSUnderlineColorAttributeName
case
.
strikethroughColor
:
return
NSStrikethroughColorAttributeName
case
.
obliqueness
:
return
NSObliquenessAttributeName
case
.
expansion
:
return
NSExpansionAttributeName
case
.
writingDirection
:
return
NSWritingDirectionAttributeName
case
.
verticalGlyphForm
:
return
NSVerticalGlyphFormAttributeName
}
}
extension
NSAttributedString
{
/**
Retrieves the character attributes that are currently applied.
- Parameter at location: An Int.
- Parameter effectiveRange: An optional NSRangePointer.
- Returns: A Dictionary of CharacterAttribute type keys and Any type values.
*/
open
func
characterAttributes
(
at
location
:
Int
,
effectiveRange
:
NSRangePointer
?)
->
[
CharacterAttribute
:
Any
]
{
var
ca
=
[
CharacterAttribute
:
Any
]()
attributes
(
at
:
location
,
effectiveRange
:
effectiveRange
)
.
forEach
{
(
key
,
value
)
in
guard
let
attribute
=
CharacterAttribute
.
init
(
rawValue
:
key
)
else
{
return
}
ca
[
attribute
]
=
value
}
return
ca
}
}
extension
NSMutableAttributedString
{
/**
Adds a character attribute to a given range.
- Parameter characterAttribute: A CharacterAttribute.
- Parameter value: Any type.
- Parameter range: A NSRange.
*/
open
func
addAttribute
(
characterAttribute
:
CharacterAttribute
,
value
:
Any
,
range
:
NSRange
)
{
addAttribute
(
characterAttribute
.
rawValue
,
value
:
value
,
range
:
range
)
}
/**
Removes a character attribute from a given range.
- Parameter characterAttribute: A CharacterAttribute.
- Parameter range: A NSRange.
*/
open
func
removeAttribute
(
characterAttribute
:
CharacterAttribute
,
range
:
NSRange
)
{
removeAttribute
(
characterAttribute
.
rawValue
,
range
:
range
)
}
}
Sources/iOS/Editor.swift
View file @
c693872f
...
...
@@ -30,130 +30,44 @@
import
UIKit
public
enum
CharacterAttribute
:
String
{
case
font
=
"NSFontAttributeName"
case
paragraphStyle
=
"NSParagraphStyleAttributeName"
case
forgroundColor
=
"NSForegroundColorAttributeName"
case
backgroundColor
=
"NSBackgroundColorAttributeName"
case
ligature
=
"NSLigatureAttributeName"
case
kern
=
"NSKernAttributeName"
case
strikethroughStyle
=
"NSStrikethroughStyleAttributeName"
case
underlineStyle
=
"NSUnderlineStyleAttributeName"
case
strokeColor
=
"NSStrokeColorAttributeName"
case
strokeWidth
=
"NSStrokeWidthAttributeName"
case
shadow
=
"NSShadowAttributeName"
case
textEffect
=
"NSTextEffectAttributeName"
case
attachment
=
"NSAttachmentAttributeName"
case
link
=
"NSLinkAttributeName"
case
baselineOffset
=
"NSBaselineOffsetAttributeName"
case
underlineColor
=
"NSUnderlineColorAttributeName"
case
strikethroughColor
=
"NSStrikethroughColorAttributeName"
case
obliqueness
=
"NSObliquenessAttributeName"
case
expansion
=
"NSExpansionAttributeName"
case
writingDirection
=
"NSWritingDirectionAttributeName"
case
verticalGlyphForm
=
"NSVerticalGlyphFormAttributeName"
}
public
func
CharacterAttributeToValue
(
attribute
:
CharacterAttribute
)
->
String
{
switch
attribute
{
case
.
font
:
return
NSFontAttributeName
case
.
paragraphStyle
:
return
NSParagraphStyleAttributeName
case
.
forgroundColor
:
return
NSForegroundColorAttributeName
case
.
backgroundColor
:
return
NSBackgroundColorAttributeName
case
.
ligature
:
return
NSLigatureAttributeName
case
.
kern
:
return
NSKernAttributeName
case
.
strikethroughStyle
:
return
NSStrikethroughStyleAttributeName
case
.
underlineStyle
:
return
NSUnderlineStyleAttributeName
case
.
strokeColor
:
return
NSStrokeColorAttributeName
case
.
strokeWidth
:
return
NSStrokeWidthAttributeName
case
.
shadow
:
return
NSShadowAttributeName
case
.
textEffect
:
return
NSTextEffectAttributeName
case
.
attachment
:
return
NSAttachmentAttributeName
case
.
link
:
return
NSLinkAttributeName
case
.
baselineOffset
:
return
NSBaselineOffsetAttributeName
case
.
underlineColor
:
return
NSUnderlineColorAttributeName
case
.
strikethroughColor
:
return
NSStrikethroughColorAttributeName
case
.
obliqueness
:
return
NSObliquenessAttributeName
case
.
expansion
:
return
NSExpansionAttributeName
case
.
writingDirection
:
return
NSWritingDirectionAttributeName
case
.
verticalGlyphForm
:
return
NSVerticalGlyphFormAttributeName
}
}
/// A memory reference to the CharacterAttribute instance for String extensions.
//private var CharacterAttributeKey: UInt8 = 0
//public struct CharacterAttribute {
//}
//extension String {
/// characterAttribute reference.
// public private(set) var characterAttribute: CharacterAttribute {
// get {
// return AssociatedObject(base: self, key: &CharacterAttributeKey) {
// return CharacterAttribute()
// }
// }
// set(value) {
// AssociateObject(base: self, key: &CharacterAttributeKey, value: value)
// }
// }
//}
extension
NSAttributedString
{
open
func
characterAttributes
(
at
index
:
Int
,
effectiveRange
:
NSRangePointer
?)
->
[
CharacterAttribute
:
Any
]
{
var
ca
=
[
CharacterAttribute
:
Any
]()
attributes
(
at
:
index
,
effectiveRange
:
effectiveRange
)
.
forEach
{
(
key
,
value
)
in
guard
let
attribute
=
CharacterAttribute
.
init
(
rawValue
:
key
)
else
{
return
}
ca
[
attribute
]
=
value
}
return
ca
}
}
public
enum
ParagraphAttribute
{
}
public
enum
DocumentAttribute
{
}
@objc(EditorDelegate)
public
protocol
EditorDelegate
{
/**
An optional delegation method that is executed when
text will be processed during editing.
- Parameter text: The Text instance assodicated with the
delegation object.
- Parameter textStorage: The TextStorage instance
associated with the delegation object.
- Parameter string: The string value that is currently
being edited.
- Parameter range: The range of characters that are being
edited.
*/
@objc
optional
func
editor
(
editor
:
Editor
,
willProcess
textStorage
:
TextStorage
,
string
:
String
,
range
:
NSRange
)
/**
An optional delegation method that is executed after
the edit processing has completed.
- Parameter text: The Text instance assodicated with the
delegation object.
- Parameter textStorage: The TextStorage instance
associated with the delegation object.
- Parameter string: The string value that was edited.
- Parameter result: A NSTextCheckingResult associated
with the processing result.
- Parameter flags: Matching flags.
- Parameter stop: Halts a service which is either
publishing or resolving.
*/
@objc
optional
func
editor
(
editor
:
Editor
,
didProcess
textStorage
:
TextStorage
,
string
:
String
,
result
:
NSTextCheckingResult
?,
flags
:
NSRegularExpression
.
MatchingFlags
,
stop
:
UnsafeMutablePointer
<
ObjCBool
>
)
}
open
class
Editor
:
View
{
///
A reference to the Text
.
open
fileprivate
(
set
)
var
text
:
Text
!
///
TextStorage instance that is observed while editing
.
open
fileprivate
(
set
)
var
text
Storage
:
TextStorage
!
/// A reference to the NSTextContainer.
open
fileprivate
(
set
)
var
textContainer
:
NSTextContainer
!
...
...
@@ -167,6 +81,37 @@ open class Editor: View {
/// A reference to an EditorDelegate.
open
weak
var
delegate
:
EditorDelegate
?
/// The string pattern to match within the textStorage.
open
var
pattern
=
"(^|
\\
s)#[
\\
d
\\
w_
\u{203C}\u{2049}\u{20E3}\u{2122}\u{2139}\u{2194}
-
\u{2199}\u{21A9}
-
\u{21AA}\u{231A}
-
\u{231B}\u{23E9}
-
\u{23EC}\u{23F0}\u{23F3}\u{24C2}\u{25AA}
-
\u{25AB}\u{25B6}\u{25C0}\u{25FB}
-
\u{25FE}\u{2600}
-
\u{2601}\u{260E}\u{2611}\u{2614}
-
\u{2615}\u{261D}\u{263A}\u{2648}
-
\u{2653}\u{2660}\u{2663}\u{2665}
-
\u{2666}\u{2668}\u{267B}\u{267F}\u{2693}\u{26A0}
-
\u{26A1}\u{26AA}
-
\u{26AB}\u{26BD}
-
\u{26BE}\u{26C4}
-
\u{26C5}\u{26CE}\u{26D4}\u{26EA}\u{26F2}
-
\u{26F3}\u{26F5}\u{26FA}\u{26FD}\u{2702}\u{2705}\u{2708}
-
\u{270C}\u{270F}\u{2712}\u{2714}\u{2716}\u{2728}\u{2733}
-
\u{2734}\u{2744}\u{2747}\u{274C}\u{274E}\u{2753}
-
\u{2755}\u{2757}\u{2764}\u{2795}
-
\u{2797}\u{27A1}\u{27B0}\u{2934}
-
\u{2935}\u{2B05}
-
\u{2B07}\u{2B1B}
-
\u{2B1C}\u{2B50}\u{2B55}\u{3030}\u{303D}\u{3297}\u{3299}\u{1F004}\u{1F0CF}\u{1F170}
-
\u{1F171}\u{1F17E}
-
\u{1F17F}\u{1F18E}\u{1F191}
-
\u{1F19A}\u{1F1E7}
-
\u{1F1EC}\u{1F1EE}
-
\u{1F1F0}\u{1F1F3}\u{1F1F5}\u{1F1F7}
-
\u{1F1FA}\u{1F201}
-
\u{1F202}\u{1F21A}\u{1F22F}\u{1F232}
-
\u{1F23A}\u{1F250}
-
\u{1F251}\u{1F300}
-
\u{1F320}\u{1F330}
-
\u{1F335}\u{1F337}
-
\u{1F37C}\u{1F380}
-
\u{1F393}\u{1F3A0}
-
\u{1F3C4}\u{1F3C6}
-
\u{1F3CA}\u{1F3E0}
-
\u{1F3F0}\u{1F400}
-
\u{1F43E}\u{1F440}\u{1F442}
-
\u{1F4F7}\u{1F4F9}
-
\u{1F4FC}\u{1F500}
-
\u{1F507}\u{1F509}
-
\u{1F53D}\u{1F550}
-
\u{1F567}\u{1F5FB}
-
\u{1F640}\u{1F645}
-
\u{1F64F}\u{1F680}
-
\u{1F68A}
]+"
{
didSet
{
prepareRegularExpression
()
}
}
/**
A convenience property that accesses the textStorage
string.
*/
open
var
string
:
String
{
return
textStorage
.
string
}
/// An Array of matches that match the pattern expression.
open
var
matches
:
[
String
]
{
return
textStorage
.
expression
!.
matches
(
in
:
string
,
options
:
[],
range
:
NSMakeRange
(
0
,
string
.
utf16
.
count
))
.
map
{
[
unowned
self
]
in
(
self
.
string
as
NSString
)
.
substring
(
with
:
$0
.
range
)
.
trimmed
}
}
/**
An Array of unique matches that match the pattern
expression.
*/
public
var
uniqueMatches
:
[
String
]
{
var
seen
=
[
String
:
Bool
]()
return
matches
.
filter
{
nil
==
seen
.
updateValue
(
true
,
forKey
:
$0
)
}
}
/**
Prepares the view instance when intialized. When subclassing,
it is recommended to override the prepare method
...
...
@@ -178,7 +123,7 @@ open class Editor: View {
super
.
prepare
()
prepareTextContainer
()
prepareLayoutManager
()
prepareText
()
prepareText
Storage
()
prepareTextView
()
}
}
...
...
@@ -195,11 +140,11 @@ extension Editor {
layoutManager
.
addTextContainer
(
textContainer
)
}
/// P
Repares the text
.
fileprivate
func
prepareText
()
{
text
=
Text
()
text
.
delegate
=
self
text
.
textStorage
.
addLayoutManager
(
layoutManager
)
/// P
repares the textStorage
.
fileprivate
func
prepareText
Storage
()
{
text
Storage
=
TextStorage
()
text
Storage
.
addLayoutManager
(
layoutManager
)
text
Storage
.
delegate
=
self
}
/// Prepares the textView.
...
...
@@ -207,23 +152,19 @@ extension Editor {
textView
=
TextView
(
textContainer
:
textContainer
)
layout
(
textView
)
.
edges
()
}
/// Prepares the regular expression for matching.
fileprivate
func
prepareRegularExpression
()
{
textStorage
.
expression
=
try
?
NSRegularExpression
(
pattern
:
pattern
,
options
:
[])
}
}
extension
Editor
:
TextDelegate
{
/**
When changes in the textView text are made, this delegation method
is executed with the added text string and range.
*/
public
func
textWillProcessEdit
(
text
:
Text
,
textStorage
:
TextStorage
,
string
:
String
,
range
:
NSRange
)
{
textStorage
.
removeAttribute
(
CharacterAttribute
.
font
.
rawValue
,
range
:
range
)
textStorage
.
addAttribute
(
CharacterAttribute
.
font
.
rawValue
,
value
:
RobotoFont
.
regular
,
range
:
range
)
extension
Editor
:
TextStorageDelegate
{
open
func
textStorage
(
textStorage
:
TextStorage
,
willProcessEditing
text
:
String
,
range
:
NSRange
)
{
}
/**
When a match is detected within the textView text, this delegation
method is executed with the added text string and range.
*/
public
func
textDidProcessEdit
(
text
:
Text
,
textStorage
:
TextStorage
,
string
:
String
,
result
:
NSTextCheckingResult
?,
flags
:
NSRegularExpression
.
MatchingFlags
,
stop
:
UnsafeMutablePointer
<
ObjCBool
>
)
{
textStorage
.
addAttribute
(
CharacterAttribute
.
font
.
rawValue
,
value
:
RobotoFont
.
bold
,
range
:
result
!.
range
)
open
func
textStorage
(
textStorage
:
TextStorage
,
didProcessEditing
text
:
String
,
result
:
NSTextCheckingResult
?,
flags
:
NSRegularExpression
.
MatchingFlags
,
stop
:
UnsafeMutablePointer
<
ObjCBool
>
)
{
}
}
Sources/iOS/Text.swift
deleted
100644 → 0
View file @
b55650de
/*
* Copyright (C) 2015 - 2016, Daniel Dahan and CosmicMind, Inc. <http://cosmicmind.com>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of CosmicMind nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import
UIKit
@objc(TextDelegate)
public
protocol
TextDelegate
{
/**
An optional delegation method that is executed when
text will be processed during editing.
- Parameter text: The Text instance assodicated with the
delegation object.
- Parameter textStorage: The TextStorage instance
associated with the delegation object.
- Parameter string: The string value that is currently
being edited.
- Parameter range: The range of characters that are being
edited.
*/
@objc
optional
func
textWillProcessEdit
(
text
:
Text
,
textStorage
:
TextStorage
,
string
:
String
,
range
:
NSRange
)
/**
An optional delegation method that is executed after
the edit processing has completed.
- Parameter text: The Text instance assodicated with the
delegation object.
- Parameter textStorage: The TextStorage instance
associated with the delegation object.
- Parameter string: The string value that was edited.
- Parameter result: A NSTextCheckingResult associated
with the processing result.
- Parameter flags: Matching flags.
- Parameter stop: Halts a service which is either
publishing or resolving.
*/
@objc
optional
func
textDidProcessEdit
(
text
:
Text
,
textStorage
:
TextStorage
,
string
:
String
,
result
:
NSTextCheckingResult
?,
flags
:
NSRegularExpression
.
MatchingFlags
,
stop
:
UnsafeMutablePointer
<
ObjCBool
>
)
}
@objc(Text)
public
class
Text
:
NSObject
{
/// The string pattern to match within the textStorage.
public
var
pattern
:
String
=
"(^|
\\
s)#[
\\
d
\\
w_
\u{203C}\u{2049}\u{20E3}\u{2122}\u{2139}\u{2194}
-
\u{2199}\u{21A9}
-
\u{21AA}\u{231A}
-
\u{231B}\u{23E9}
-
\u{23EC}\u{23F0}\u{23F3}\u{24C2}\u{25AA}
-
\u{25AB}\u{25B6}\u{25C0}\u{25FB}
-
\u{25FE}\u{2600}
-
\u{2601}\u{260E}\u{2611}\u{2614}
-
\u{2615}\u{261D}\u{263A}\u{2648}
-
\u{2653}\u{2660}\u{2663}\u{2665}
-
\u{2666}\u{2668}\u{267B}\u{267F}\u{2693}\u{26A0}
-
\u{26A1}\u{26AA}
-
\u{26AB}\u{26BD}
-
\u{26BE}\u{26C4}
-
\u{26C5}\u{26CE}\u{26D4}\u{26EA}\u{26F2}
-
\u{26F3}\u{26F5}\u{26FA}\u{26FD}\u{2702}\u{2705}\u{2708}
-
\u{270C}\u{270F}\u{2712}\u{2714}\u{2716}\u{2728}\u{2733}
-
\u{2734}\u{2744}\u{2747}\u{274C}\u{274E}\u{2753}
-
\u{2755}\u{2757}\u{2764}\u{2795}
-
\u{2797}\u{27A1}\u{27B0}\u{2934}
-
\u{2935}\u{2B05}
-
\u{2B07}\u{2B1B}
-
\u{2B1C}\u{2B50}\u{2B55}\u{3030}\u{303D}\u{3297}\u{3299}\u{1F004}\u{1F0CF}\u{1F170}
-
\u{1F171}\u{1F17E}
-
\u{1F17F}\u{1F18E}\u{1F191}
-
\u{1F19A}\u{1F1E7}
-
\u{1F1EC}\u{1F1EE}
-
\u{1F1F0}\u{1F1F3}\u{1F1F5}\u{1F1F7}
-
\u{1F1FA}\u{1F201}
-
\u{1F202}\u{1F21A}\u{1F22F}\u{1F232}
-
\u{1F23A}\u{1F250}
-
\u{1F251}\u{1F300}
-
\u{1F320}\u{1F330}
-
\u{1F335}\u{1F337}
-
\u{1F37C}\u{1F380}
-
\u{1F393}\u{1F3A0}
-
\u{1F3C4}\u{1F3C6}
-
\u{1F3CA}\u{1F3E0}
-
\u{1F3F0}\u{1F400}
-
\u{1F43E}\u{1F440}\u{1F442}
-
\u{1F4F7}\u{1F4F9}
-
\u{1F4FC}\u{1F500}
-
\u{1F507}\u{1F509}
-
\u{1F53D}\u{1F550}
-
\u{1F567}\u{1F5FB}
-
\u{1F640}\u{1F645}
-
\u{1F64F}\u{1F680}
-
\u{1F68A}
]+"
{
didSet
{
prepareTextStorageExpression
()
}
}
/// TextStorage instance that is observed while editing.
public
private(set)
var
textStorage
:
TextStorage
=
TextStorage
()
/// Delegation object for pre and post text processing.
open
weak
var
delegate
:
TextDelegate
?
/// Initializer.
public
override
init
()
{
super
.
init
()
prepareTextStorageExpression
()
prepareTextStorageProcessingCallbacks
()
}
/**
A convenience property that accesses the textStorage
string.
*/
public
var
string
:
String
{
return
textStorage
.
string
}
/// An Array of matches that match the pattern expression.
public
var
matches
:
Array
<
String
>
{
return
textStorage
.
expression
!.
matches
(
in
:
string
,
options
:
[],
range
:
NSMakeRange
(
0
,
string
.
utf16
.
count
))
.
map
{
[
unowned
self
]
in
(
self
.
string
as
NSString
)
.
substring
(
with
:
$0
.
range
)
.
trimmed
}
}
/**
An Array of unique matches that match the pattern
expression.
*/
public
var
uniqueMatches
:
Array
<
String
>
{
var
seen
:
[
String
:
Bool
]
=
[:]
return
matches
.
filter
{
nil
==
seen
.
updateValue
(
true
,
forKey
:
$0
)
}
}
/// Prepares the TextStorage regular expression for matching.
private
func
prepareTextStorageExpression
()
{
textStorage
.
expression
=
try
?
NSRegularExpression
(
pattern
:
pattern
,
options
:
[])
}
/// Prepares the pre and post processing callbacks.
private
func
prepareTextStorageProcessingCallbacks
()
{
textStorage
.
textWillProcessEdit
=
{
[
weak
self
]
(
textStorage
:
TextStorage
,
string
:
String
,
range
:
NSRange
)
->
Void
in
if
let
s
:
Text
=
self
{
s
.
delegate
?
.
textWillProcessEdit
?(
text
:
s
,
textStorage
:
textStorage
,
string
:
string
,
range
:
range
)
}
}
textStorage
.
textDidProcessEdit
=
{
[
weak
self
]
(
textStorage
:
TextStorage
,
result
:
NSTextCheckingResult
?,
flags
:
NSRegularExpression
.
MatchingFlags
,
stop
:
UnsafeMutablePointer
<
ObjCBool
>
)
->
Void
in
if
let
s
:
Text
=
self
{
s
.
delegate
?
.
textDidProcessEdit
?(
text
:
s
,
textStorage
:
textStorage
,
string
:
textStorage
.
string
,
result
:
result
,
flags
:
flags
,
stop
:
stop
)
}
}
}
}
Sources/iOS/TextStorage.swift
View file @
c693872f
...
...
@@ -30,21 +30,37 @@
import
UIKit
internal
typealias
TextWillProcessEdit
=
(
TextStorage
,
String
,
NSRange
)
->
Void
internal
typealias
TextDidProcessEdit
=
(
TextStorage
,
NSTextCheckingResult
?,
NSRegularExpression
.
MatchingFlags
,
UnsafeMutablePointer
<
ObjCBool
>
)
->
Void
public
class
TextStorage
:
NSTextStorage
{
/// A callback that is executed when a process edit will happen.
internal
var
textWillProcessEdit
:
TextWillProcessEdit
?
@objc(TextStorageDelegate)
public
protocol
TextStorageDelegate
:
NSTextStorageDelegate
{
/**
A delegation method that is executed when text will be
processed during editing.
- Parameter textStorage: A TextStorage.
- Parameter willProcessEditing text: A String.
- Parameter range: A NSRange.
*/
@objc
optional
func
textStorage
(
textStorage
:
TextStorage
,
willProcessEditing
text
:
String
,
range
:
NSRange
)
/// A callback that is executed when a process edit did happen.
internal
var
textDidProcessEdit
:
TextDidProcessEdit
?
/**
A delegation method that is executed when text has been
processed after editing.
- Parameter textStorage: A TextStorage.
- Parameter didProcessEditing text: A String.
- Parameter result: An optional NSTextCheckingResult.
- Parameter flags: NSRegularExpression.MatchingFlags.
- Parameter top: An UnsafeMutablePointer<ObjCBool>.
*/
@objc
optional
func
textStorage
(
textStorage
:
TextStorage
,
didProcessEditing
text
:
String
,
result
:
NSTextCheckingResult
?,
flags
:
NSRegularExpression
.
MatchingFlags
,
stop
:
UnsafeMutablePointer
<
ObjCBool
>
)
}
open
class
TextStorage
:
NSTextStorage
{
/// A storage facility for attributed text.
public
lazy
var
store
:
NSMutableAttributedString
=
NSMutableAttributedString
()
open
fileprivate
(
set
)
var
store
:
NSMutableAttributedString
!
/// The regular expression to match text fragments against.
public
var
expression
:
NSRegularExpression
?
open
var
expression
:
NSRegularExpression
?
/// Initializer.
public
required
init
?(
coder
aDecoder
:
NSCoder
)
{
...
...
@@ -54,22 +70,38 @@ public class TextStorage: NSTextStorage {
/// Initializer.
public
override
init
()
{
super
.
init
()
prepareStore
()
}
}
extension
TextStorage
{
/// Prepare the store.
fileprivate
func
prepareStore
()
{
store
=
NSMutableAttributedString
()
}
}
extension
TextStorage
{
/// A String value of the attirbutedString property.
public
override
var
string
:
String
{
open
override
var
string
:
String
{
return
store
.
string
}
/// Processes the text when editing.
public
override
func
processEditing
()
{
open
override
func
processEditing
()
{
let
range
:
NSRange
=
(
string
as
NSString
)
.
paragraphRange
(
for
:
editedRange
)
textWillProcessEdit
?(
self
,
string
,
range
)
(
delegate
as?
TextStorageDelegate
)?
.
textStorage
?(
textStorage
:
self
,
willProcessEditing
:
string
,
range
:
range
)
expression
!.
enumerateMatches
(
in
:
string
,
options
:
[],
range
:
range
)
{
[
weak
self
]
(
result
:
NSTextCheckingResult
?,
flags
:
NSRegularExpression
.
MatchingFlags
,
stop
:
UnsafeMutablePointer
<
ObjCBool
>
)
->
Void
in
guard
let
s
=
self
else
{
return
}
expression
!.
enumerateMatches
(
in
:
string
,
options
:
[],
range
:
range
)
{
(
result
:
NSTextCheckingResult
?,
flags
:
NSRegularExpression
.
MatchingFlags
,
stop
:
UnsafeMutablePointer
<
ObjCBool
>
)
->
Void
in
self
.
textDidProcessEdit
?(
self
,
result
,
flags
,
stop
)
(
s
.
delegate
as?
TextStorageDelegate
)?
.
textStorage
!
(
textStorage
:
s
,
didProcessEditing
:
s
.
string
,
result
:
result
,
flags
:
flags
,
stop
:
stop
)
}
super
.
processEditing
()
}
...
...
@@ -85,7 +117,7 @@ public class TextStorage: NSTextStorage {
If you don't need this value, pass NULL.
- Returns: The attributes for the character at index.
*/
public
override
func
attributes
(
at
location
:
Int
,
effectiveRange
range
:
NSRangePointer
?)
->
[
String
:
Any
]
{
open
override
func
attributes
(
at
location
:
Int
,
effectiveRange
range
:
NSRangePointer
?)
->
[
String
:
Any
]
{
return
store
.
attributes
(
at
:
location
,
effectiveRange
:
range
)
}
...
...
@@ -95,9 +127,10 @@ public class TextStorage: NSTextStorage {
- Parameter str: The string value that the characters
will be replaced with.
*/
public
override
func
replaceCharacters
(
in
range
:
NSRange
,
with
str
:
String
)
{
open
override
func
replaceCharacters
(
in
range
:
NSRange
,
with
str
:
String
)
{
store
.
replaceCharacters
(
in
:
range
,
with
:
str
)
edited
(
NSTextStorageEditActions
.
editedCharacters
,
range
:
range
,
changeInLength
:
str
.
utf16
.
count
-
range
.
length
)
edited
(
.
editedCharacters
,
range
:
range
,
changeInLength
:
str
.
utf16
.
count
-
range
.
length
)
}
/**
...
...
@@ -106,8 +139,9 @@ public class TextStorage: NSTextStorage {
- Parameter range: A range of characters that will have their
attributes updated.
*/
public
override
func
setAttributes
(
_
attrs
:
[
String
:
Any
]?,
range
:
NSRange
)
{
open
override
func
setAttributes
(
_
attrs
:
[
String
:
Any
]?,
range
:
NSRange
)
{
store
.
setAttributes
(
attrs
,
range
:
range
)
edited
(
NSTextStorageEditActions
.
editedAttributes
,
range
:
range
,
changeInLength
:
0
)
edited
(
.
editedAttributes
,
range
:
range
,
changeInLength
:
0
)
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment