Commit f5510c66 by Daniel Dahan

adding TextView, Image helpers, and String helpers

parent 3ff6b6f5
Pod::Spec.new do |s|
s.name = 'MK'
s.version = '1.26.0'
s.version = '1.27.0'
s.license = { :type => "AGPL-3.0", :file => "LICENSE" }
s.summary = 'A beautiful Material Design framework in Swift.'
s.homepage = 'http://materialkit.io'
......
......@@ -30,6 +30,7 @@ Run carthage to build the framework and drag the built MaterialKit.framework int
* [MaterialColor](#materialcolor)
* [TextField](#textfield)
* [TextView](#textview)
* [MaterialLayer](#materiallayer)
* [MaterialView](#materialview)
* [MaterialPulseView](#materialpulseview)
......@@ -41,6 +42,12 @@ Run carthage to build the framework and drag the built MaterialKit.framework int
* [NavigationBarView](#navigationbarview)
* [SideNavigationViewController](#sidenavigationviewcontroller)
* [CaptureView](#captureview)
* [Resize Image](#resizeimage)
* [Crop Image](#cropimage)
* [Save Image To PhotoLibrary](#saveimagetophotolibrary)
* [Asynchronous Image Loading](#asynchronousimageloading)
* [Lines of Text](#linesoftext)
* [Trim Whitespace](#trimwhitespace)
### Upcoming
......@@ -48,7 +55,6 @@ Run carthage to build the framework and drag the built MaterialKit.framework int
* SearchBarViewController
* TabView
* TabViewController
* TextView
* Scrolling Techniques
* More Examples
......@@ -86,6 +92,66 @@ nameField.clearButtonMode = .WhileEditing
view.addSubview(nameField)
```
<a name="textview"/>
### TextView
Easily match any regular expression pattern in a body of text. Below is an example of the default hashtag pattern matching.
![MaterialKitTextView](http://www.materialkit.io/MK/MaterialKitTextView.gif)
```swift
class ViewController: UIViewController, TextDelegate, TextViewDelegate {
// ...
lazy var text: Text = Text()
var textView: TextView?
// ...
func prepareTextView() {
let layoutManager: NSLayoutManager = NSLayoutManager()
let textContainer = NSTextContainer(size: bounds.size)
layoutManager.addTextContainer(textContainer)
text.delegate = self
text.textStorage.addLayoutManager(layoutManager)
textView = TextView(frame: CGRectNull, textContainer: textContainer)
textView?.delegate = self
textView!.editable = true
textView!.selectable = true
textView!.font = UIFont.systemFontOfSize(16)
textView!.text = note?["text"] as? String
textView!.placeholderLabel = UILabel()
textView!.placeholderLabel!.textColor = UIColor.grayColor()
let attrText: NSMutableAttributedString = NSMutableAttributedString(string: "focus your #thoughts", attributes: [NSFontAttributeName: UIFont.systemFontOfSize(16)])
attrText.addAttribute(NSFontAttributeName, value: UIFont.boldSystemFontOfSize(16), range: NSRange(location: 11, length: 9))
textView!.placeholderLabel!.attributedText = attrText
addSubview(textView!)
}
// ...
func textWillProcessEdit(text: Text, textStorage: TextStorage, string: String, range: NSRange) {
textStorage.removeAttribute(NSFontAttributeName, range: range)
textStorage.addAttribute(NSFontAttributeName, value: UIFont.systemFontOfSize(16), range: range)
}
//...
func textDidProcessEdit(text: Text, textStorage: TextStorage, string: String, result: NSTextCheckingResult?, flags: NSMatchingFlags, stop: UnsafeMutablePointer<ObjCBool>) {
textStorage.addAttribute(NSFontAttributeName, value: UIFont.boldSystemFontOfSize(16), range: result!.range)
}
// ...
}
```
<a name="materiallayer"/>
### MaterialLayer
......@@ -580,6 +646,97 @@ Add a new dimension of interactivity with CaptureView. CaptureView is a fully fu
![MaterialKitCaptureView](http://www.materialkit.io/MK/MaterialKitCaptureView.jpg)
<a name="resizeimage"/>
### Resize Image
Images come in all shapes and sizes. UIImage resize is a flexible way to resize images on the fly. The below example shows you how.
```swift
let p1: UIImage? = UIImage(named: "img1")
let p2: UIImage? = p1?.resize(toWidth: 300)
let p3: UIImage? = p1?.resize(toHeight: 200)
```
<a name="cropimage"/>
### Crop Image
Crop images easily with UIImage crop. Below is an example:
```swift
let p1: UIImage? = UIImage(named: "img1")
let p2: UIImage? = p1?.crop(toWidth: 400, toHeight: 200)
```
<a name="saveimagetophotolibrary"/>
### Save Image To PhotoLibrary
Keep the moment by saving your images to PhotoLibrary. Below is an example of cropping an image and saving it to the devices PhotoLibrary.
```swift
let p: UIImage? = UIImage(named: "img1")
p?.crop(toWidth: 400, toHeight: 200)?.writeToPhotoLibrary()
```
It is also possible to specify a target handler when saving to the PhotoLibrary.
```swift
let p: UIImage? = UIImage(named: "img1")
p?.writeToPhotoLibrary(target: self)
```
Add the PhotoLibrary save handler to the target object.
```swift
func image(image: UIImage, didFinishSavingWithError error: NSError?, contextInfo: UnsafePointer<Void>) {
let message: String = nil == error ? "Your photo has been saved!" : error!.localizedDescription
let a: UIAlertController = UIAlertController(title: "Status", message: message, preferredStyle: .Alert)
a.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
presentViewController(a, animated: true, completion: nil)
}
```
<a name="asynchronousimageloading"/>
### Asynchronous Image Loading
Not all images you may want to load will be available locally. No problem, use the UIImage class method contentsOfURL to load remote images asynchronously. Below is an example of its usage.
```swift
let url: NSURL = NSURL(string: "https://yourimage.io")!
UIImage.contentsOfURL(url) { (image: UIImage?, error: NSError?) in
if let v: UIImage = image {
// Do something
}
}
```
<a name="linesoftext"/>
### Lines of Text
Cycle through lines of text in any String. Below is an example of iterating through all lines of text in a String.
```swift
let text: String = "This is a\nblock of text\nthat has\nnewlines."
for line in text.lines {
print(line)
}
// Output:
// This is a
// block of text
// that has
// newlines.
```
<a name="trimwhitespace"/>
### Trim Whitespace
Remove the spaces and newlines from the beginning and end of a text block. Below is an example.
```swift
let text: String = " \n Hello World \n "
print(text.trim()) // Output: Hello World
```
### License
[AGPL-3.0](http://choosealicense.com/licenses/agpl-3.0/)
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
......@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.26.0</string>
<string>1.27.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program located at the root of the software package
// in a file called LICENSE. If not, see <http://www.gnu.org/licenses/>.
//
import UIKit
public extension String {
/**
:name: lines
*/
public var lines: Array<String> {
return componentsSeparatedByCharactersInSet(NSCharacterSet.newlineCharacterSet())
}
/**
:name: firstLine
*/
public var firstLine: String? {
return lines.first?.trim()
}
/**
:name: lastLine
*/
public var lastLine: String? {
return lines.last?.trim()
}
/**
:name: replaceNewLineCharater
*/
public func replaceNewLineCharater(replace: String = " ") -> String {
return componentsSeparatedByCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()).joinWithSeparator(replace).trim()
}
/**
:name: replacePunctuationCharacters
*/
public func replacePunctuationCharacters(replace: String = "") -> String {
return componentsSeparatedByCharactersInSet(NSCharacterSet.punctuationCharacterSet()).joinWithSeparator(replace).trim()
}
/**
:name: trim
*/
public func trim() -> String {
return stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
}
}
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program located at the root of the software package
// in a file called LICENSE. If not, see <http://www.gnu.org/licenses/>.
//
import UIKit
public extension UIImage {
/**
:name: crop
*/
public func crop(var toWidth w: CGFloat, var toHeight h: CGFloat) -> UIImage? {
let g: UIImage?
let b: Bool = width > height
let s: CGFloat = b ? h / height : w / width
let t: CGSize = CGSizeMake(w, h)
w = width * s
h = height * s
UIGraphicsBeginImageContext(t)
drawInRect(b ? CGRectMake(-1 * (w - t.width) / 2, 0, w, h) : CGRectMake(0, -1 * (h - t.height) / 2, w, h), blendMode: .Normal, alpha: 1)
g = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return g!
}
}
\ No newline at end of file
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program located at the root of the software package
// in a file called LICENSE. If not, see <http://www.gnu.org/licenses/>.
//
import UIKit
public extension UIImage {
/**
:name: contentsOfURL
*/
public class func contentsOfURL(URL: NSURL, completion: ((image: UIImage?, error: NSError?) -> Void)?) {
let request: NSURLRequest = NSURLRequest(URL: URL)
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) { (response: NSURLResponse?, data: NSData?, error: NSError?) -> Void in
if let v: NSError = error {
completion?(image: nil, error: v)
} else if let v: NSData = data {
completion?(image: UIImage(data: v), error: nil)
}
}
}
}
\ No newline at end of file
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program located at the root of the software package
// in a file called LICENSE. If not, see <http://www.gnu.org/licenses/>.
//
import UIKit
public extension UIImage {
/**
:name: writeToPhotoLibrary
*/
public func writeToPhotoLibrary(target t: AnyObject? = nil) {
UIImageWriteToSavedPhotosAlbum(self, t, "image:didFinishSavingWithError:contextInfo:", nil)
}
}
\ No newline at end of file
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program located at the root of the software package
// in a file called LICENSE. If not, see <http://www.gnu.org/licenses/>.
//
import UIKit
public extension UIImage {
/**
:name: internalResize
*/
private func internalResize(var toWidth w: CGFloat = 0, var toHeight h: CGFloat = 0) -> UIImage? {
if 0 < w {
h = height * w / width
} else if 0 < h {
w = width * h / height
}
let g: UIImage?
let t: CGRect = CGRectMake(0, 0, w, h)
UIGraphicsBeginImageContext(t.size)
drawInRect(t, blendMode: .Normal, alpha: 1)
g = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return g
}
/**
:name: resize
*/
public func resize(toWidth w: CGFloat) -> UIImage? {
return internalResize(toWidth: w)
}
/**
:name: resize
*/
public func resize(toHeight h: CGFloat) -> UIImage? {
return internalResize(toHeight: h)
}
}
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program located at the root of the software package
// in a file called LICENSE. If not, see <http://www.gnu.org/licenses/>.
//
import UIKit
public extension UIImage {
/**
:name: width
*/
public var width: CGFloat {
return size.width
}
/**
:name: height
*/
public var height: CGFloat {
return size.height
}
}
\ No newline at end of file
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program located at the root of the software package
// in a file called LICENSE. If not, see <http://www.gnu.org/licenses/>.
//
import UIKit
public enum ContentImageFormatType {
case PNG
case JPEG
}
\ No newline at end of file
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program located at the root of the software package
// in a file called LICENSE. If not, see <http://www.gnu.org/licenses/>.
//
import UIKit
/**
:name: unique
*/
public func unique<S: SequenceType, E: Hashable where E == S.Generator.Element>(source: S) -> [E] {
var seen: [E: Bool] = [:]
return source.filter { nil == seen.updateValue(true, forKey: $0) }
}
@objc(TextDelegate)
public protocol TextDelegate {
optional func textWillProcessEdit(text: Text, textStorage: TextStorage, string: String, range: NSRange)
optional func textDidProcessEdit(text: Text, textStorage: TextStorage, string: String, result: NSTextCheckingResult?, flags: NSMatchingFlags, stop: UnsafeMutablePointer<ObjCBool>)
}
@objc(Text)
public class Text : NSObject {
/**
:name: pattern
*/
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 {
textStorage.expression = try? NSRegularExpression(pattern: pattern, options: [])
}
}
/**
:name: textStorage
*/
public private(set) var textStorage: TextStorage = TextStorage()
/**
:name: delegate
*/
public weak var delegate: TextDelegate?
/**
:name: init
*/
public override init() {
super.init()
textStorage.expression = try? NSRegularExpression(pattern: pattern, options: [])
textStorage.textWillProcessEdit = { (textStorage: TextStorage, string: String, range: NSRange) -> Void in
self.delegate?.textWillProcessEdit?(self, textStorage: textStorage, string: string, range: range)
}
textStorage.textDidProcessEdit = { (textStorage: TextStorage, result: NSTextCheckingResult?, flags: NSMatchingFlags, stop: UnsafeMutablePointer<ObjCBool>) -> Void in
self.delegate?.textDidProcessEdit?(self, textStorage: textStorage, string: textStorage.string, result: result, flags: flags, stop: stop)
}
}
/**
:name: string
*/
public var string: String {
return textStorage.string
}
/**
:name: matches
*/
public var matches: Array<String> {
return textStorage.expression!.matchesInString(string, options: [], range: NSMakeRange(0, string.utf16.count)).map {
(self.string as NSString).substringWithRange($0.range).stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
}
}
/**
:name: uniqueMatches
*/
public var uniqueMatches: Array<String> {
return unique(matches)
}
}
\ No newline at end of file
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program located at the root of the software package
// in a file called LICENSE. If not, see <http://www.gnu.org/licenses/>.
//
import UIKit
internal typealias TextWillProcessEdit = (TextStorage, String, NSRange) -> Void
internal typealias TextDidProcessEdit = (TextStorage, NSTextCheckingResult?, NSMatchingFlags, UnsafeMutablePointer<ObjCBool>) -> Void
public class TextStorage: NSTextStorage {
/**
:name: store
*/
private lazy var store: NSMutableAttributedString = NSMutableAttributedString()
/**
:name: expression
*/
internal var expression: NSRegularExpression?
/**
:name: textWillProcessEdit
*/
internal var textWillProcessEdit: TextWillProcessEdit?
/**
:name: textDidProcessEdit
*/
internal var textDidProcessEdit: TextDidProcessEdit?
/**
:name: init
*/
public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
/**
:name: init
*/
public override init() {
super.init()
}
/**
:name: string
*/
override public var string: String {
get {
return store.string
}
}
/**
:name: processEditing
*/
public override func processEditing() {
let range: NSRange = (string as NSString).paragraphRangeForRange(editedRange)
textWillProcessEdit?(self, string, range)
expression!.enumerateMatchesInString(string, options: [], range: range) { (result: NSTextCheckingResult?, flags: NSMatchingFlags, stop: UnsafeMutablePointer<ObjCBool>) -> Void in
self.textDidProcessEdit?(self, result, flags, stop)
}
super.processEditing()
}
/**
:name: attributesAtIndex
*/
public override func attributesAtIndex(location: Int, effectiveRange range: NSRangePointer) -> [String : AnyObject] {
return store.attributesAtIndex(location, effectiveRange: range)
}
/**
:name: replaceCharactersInRange
*/
public override func replaceCharactersInRange(range: NSRange, withString str: String) {
store.replaceCharactersInRange(range, withString: str)
edited(NSTextStorageEditActions.EditedCharacters, range: range, changeInLength: str.utf16.count - range.length)
}
/**
:name: setAttributes
*/
public override func setAttributes(attrs: [String : AnyObject]?, range: NSRange) {
store.setAttributes(attrs, range: range)
edited(NSTextStorageEditActions.EditedAttributes, range: range, changeInLength: 0)
}
}
\ No newline at end of file
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program located at the root of the software package
// in a file called LICENSE. If not, see <http://www.gnu.org/licenses/>.
//
import UIKit
public protocol TextViewDelegate : UITextViewDelegate {}
public class TextView: UITextView {
/**
:name: init
*/
public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
prepareView()
}
/**
:name: init
*/
public override init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
prepareView()
}
//
// :name: deinit
//
deinit {
NSNotificationCenter.defaultCenter().removeObserver(self, name: UITextViewTextDidChangeNotification, object: nil)
}
/**
:name: placeholder
*/
public var placeholderLabel: UILabel? {
didSet {
if let p = placeholderLabel {
p.translatesAutoresizingMaskIntoConstraints = false
p.font = font
p.textAlignment = textAlignment
p.numberOfLines = 0
p.backgroundColor = .clearColor()
addSubview(p)
updateLabelConstraints()
textViewTextDidChange()
}
}
}
/**
:name: text
*/
public override var text: String! {
didSet {
textViewTextDidChange()
}
}
/**
:name: attributedText
*/
public override var attributedText: NSAttributedString! {
didSet {
textViewTextDidChange()
}
}
/**
:name: textContainerInset
*/
public override var textContainerInset: UIEdgeInsets {
didSet {
updateLabelConstraints()
}
}
public override func layoutSubviews() {
super.layoutSubviews()
placeholderLabel?.preferredMaxLayoutWidth = textContainer.size.width - textContainer.lineFragmentPadding * 2
}
/**
:name: updateLabelConstraints
*/
internal func updateLabelConstraints() {
if let p = placeholderLabel {
removeConstraints(constraints)
addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-(left)-[placeholderLabel]-(right)-|", options: [], metrics: ["left": textContainerInset.left + textContainer.lineFragmentPadding, "right": textContainerInset.right + textContainer.lineFragmentPadding], views: ["placeholderLabel": p]))
addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-(top)-[placeholderLabel]-(bottom)-|", options: [], metrics: ["top": textContainerInset.top, "bottom": textContainerInset.bottom], views: ["placeholderLabel": p]))
}
}
//
// :name: textViewTextDidChange
//
internal func textViewTextDidChange() {
if let p = placeholderLabel {
p.hidden = !text.isEmpty
}
}
//
// :name: prepareView
//
private func prepareView() {
textContainerInset = UIEdgeInsetsMake(16, 16, 16, 16)
backgroundColor = .clearColor()
NSNotificationCenter.defaultCenter().removeObserver(self, name: UITextViewTextDidChangeNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "textViewTextDidChange", name: UITextViewTextDidChangeNotification, object: nil)
updateLabelConstraints()
}
}
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>..
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment