mirror of
https://github.com/oxen-io/session-ios.git
synced 2023-12-13 21:30:14 +01:00
Add brush view controller.
This commit is contained in:
parent
00aa5be55d
commit
bc31c8fcf4
9 changed files with 314 additions and 49 deletions
|
@ -13,6 +13,8 @@
|
|||
34074F62203D0CBE004596AE /* OWSSounds.h in Headers */ = {isa = PBXBuildFile; fileRef = 34074F60203D0CBE004596AE /* OWSSounds.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
34080EFE2225F96D0087E99F /* ImageEditorPaletteView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34080EFD2225F96D0087E99F /* ImageEditorPaletteView.swift */; };
|
||||
34080F0022282C880087E99F /* AttachmentCaptionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34080EFF22282C880087E99F /* AttachmentCaptionViewController.swift */; };
|
||||
34080F02222853E30087E99F /* ImageEditorBrushViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34080F01222853E30087E99F /* ImageEditorBrushViewController.swift */; };
|
||||
34080F04222858DC0087E99F /* OWSViewController+ImageEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34080F03222858DC0087E99F /* OWSViewController+ImageEditor.swift */; };
|
||||
340B02BA1FA0D6C700F9CFEC /* ConversationViewItemTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 340B02B91FA0D6C700F9CFEC /* ConversationViewItemTest.m */; };
|
||||
340FC8A9204DAC8D007AEB0F /* NotificationSettingsOptionsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC87B204DAC8C007AEB0F /* NotificationSettingsOptionsViewController.m */; };
|
||||
340FC8AA204DAC8D007AEB0F /* NotificationSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC87C204DAC8C007AEB0F /* NotificationSettingsViewController.m */; };
|
||||
|
@ -640,6 +642,8 @@
|
|||
34074F60203D0CBE004596AE /* OWSSounds.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSSounds.h; sourceTree = "<group>"; };
|
||||
34080EFD2225F96D0087E99F /* ImageEditorPaletteView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageEditorPaletteView.swift; sourceTree = "<group>"; };
|
||||
34080EFF22282C880087E99F /* AttachmentCaptionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AttachmentCaptionViewController.swift; sourceTree = "<group>"; };
|
||||
34080F01222853E30087E99F /* ImageEditorBrushViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageEditorBrushViewController.swift; sourceTree = "<group>"; };
|
||||
34080F03222858DC0087E99F /* OWSViewController+ImageEditor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "OWSViewController+ImageEditor.swift"; sourceTree = "<group>"; };
|
||||
340B02B61F9FD31800F9CFEC /* he */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = he; path = translations/he.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
340B02B91FA0D6C700F9CFEC /* ConversationViewItemTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ConversationViewItemTest.m; sourceTree = "<group>"; };
|
||||
340FC87B204DAC8C007AEB0F /* NotificationSettingsOptionsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NotificationSettingsOptionsViewController.m; sourceTree = "<group>"; };
|
||||
|
@ -1914,6 +1918,7 @@
|
|||
34BEDB0C21C405B0007B0EAE /* ImageEditor */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
34080F01222853E30087E99F /* ImageEditorBrushViewController.swift */,
|
||||
34BBC850220B8EEF00857249 /* ImageEditorCanvasView.swift */,
|
||||
34BBC853220C7ADA00857249 /* ImageEditorContents.swift */,
|
||||
34BBC84E220B8A0100857249 /* ImageEditorCropViewController.swift */,
|
||||
|
@ -1927,6 +1932,7 @@
|
|||
34BBC84A220B2CB200857249 /* ImageEditorTextViewController.swift */,
|
||||
34BEDB1221C43F69007B0EAE /* ImageEditorView.swift */,
|
||||
34BBC856220C7ADA00857249 /* OrderedDictionary.swift */,
|
||||
34080F03222858DC0087E99F /* OWSViewController+ImageEditor.swift */,
|
||||
);
|
||||
path = ImageEditor;
|
||||
sourceTree = "<group>";
|
||||
|
@ -3390,6 +3396,7 @@
|
|||
34D5872F208E2C4200D2255A /* OWS109OutgoingMessageState.m in Sources */,
|
||||
34AC09F8211B39B100997B47 /* CountryCodeViewController.m in Sources */,
|
||||
451F8A341FD710C3005CB9DA /* FullTextSearcher.swift in Sources */,
|
||||
34080F04222858DC0087E99F /* OWSViewController+ImageEditor.swift in Sources */,
|
||||
346129FE1FD5F31400532771 /* OWS106EnsureProfileComplete.swift in Sources */,
|
||||
34AC0A10211B39EA00997B47 /* TappableView.swift in Sources */,
|
||||
346129F91FD5F31400532771 /* OWS104CreateRecipientIdentities.m in Sources */,
|
||||
|
@ -3409,6 +3416,7 @@
|
|||
346941A3215D2EE400B5BFAD /* Theme.m in Sources */,
|
||||
4C23A5F2215C4ADE00534937 /* SheetViewController.swift in Sources */,
|
||||
34BBC84D220B2D0800857249 /* ImageEditorPinchGestureRecognizer.swift in Sources */,
|
||||
34080F02222853E30087E99F /* ImageEditorBrushViewController.swift in Sources */,
|
||||
34AC0A14211B39EA00997B47 /* ContactCellView.m in Sources */,
|
||||
34AC0A15211B39EA00997B47 /* ContactsViewHelper.m in Sources */,
|
||||
346129FF1FD5F31400532771 /* OWS103EnableVideoCalling.m in Sources */,
|
||||
|
|
|
@ -279,17 +279,7 @@ public class AttachmentApprovalViewController: UIPageViewController, UIPageViewC
|
|||
let firstViewController = viewControllers.first as? AttachmentPrepViewController {
|
||||
navigationBarItems = firstViewController.navigationBarItems()
|
||||
}
|
||||
guard navigationBarItems.count > 0 else {
|
||||
self.navigationItem.rightBarButtonItems = []
|
||||
return
|
||||
}
|
||||
|
||||
let stackView = UIStackView(arrangedSubviews: navigationBarItems)
|
||||
stackView.axis = .horizontal
|
||||
stackView.spacing = 8
|
||||
stackView.alignment = .center
|
||||
|
||||
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: stackView)
|
||||
updateNavigationBar(navigationBarItems: navigationBarItems)
|
||||
}
|
||||
|
||||
// MARK: - View Helpers
|
||||
|
|
|
@ -0,0 +1,231 @@
|
|||
//
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
//@objc
|
||||
//public protocol ImageEditorViewDelegate: class {
|
||||
// func imageEditor(presentFullScreenOverlay viewController: UIViewController,
|
||||
// withNavigation: Bool)
|
||||
// func imageEditorPresentCaptionView()
|
||||
// func imageEditorUpdateNavigationBar()
|
||||
//}
|
||||
|
||||
// MARK: -
|
||||
|
||||
@objc
|
||||
public protocol ImageEditorBrushViewControllerDelegate: class {
|
||||
func brushDidComplete()
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
// A view for editing text item in image editor.
|
||||
public class ImageEditorBrushViewController: OWSViewController {
|
||||
|
||||
private weak var delegate: ImageEditorBrushViewControllerDelegate?
|
||||
|
||||
private let model: ImageEditorModel
|
||||
|
||||
private let canvasView: ImageEditorCanvasView
|
||||
|
||||
private let paletteView = ImageEditorPaletteView()
|
||||
|
||||
private var brushGestureRecognizer: ImageEditorPanGestureRecognizer?
|
||||
|
||||
init(delegate: ImageEditorBrushViewControllerDelegate,
|
||||
model: ImageEditorModel) {
|
||||
self.delegate = delegate
|
||||
self.model = model
|
||||
self.canvasView = ImageEditorCanvasView(model: model)
|
||||
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
|
||||
model.add(observer: self)
|
||||
}
|
||||
|
||||
@available(*, unavailable, message: "use other init() instead.")
|
||||
required public init?(coder aDecoder: NSCoder) {
|
||||
notImplemented()
|
||||
}
|
||||
|
||||
// MARK: - View Lifecycle
|
||||
|
||||
public override func loadView() {
|
||||
self.view = UIView()
|
||||
self.view.backgroundColor = .black
|
||||
|
||||
canvasView.configureSubviews()
|
||||
self.view.addSubview(canvasView)
|
||||
canvasView.autoPinEdgesToSuperviewEdges()
|
||||
|
||||
paletteView.delegate = self
|
||||
self.view.addSubview(paletteView)
|
||||
paletteView.autoVCenterInSuperview()
|
||||
paletteView.autoPinEdge(toSuperviewEdge: .leading, withInset: 20)
|
||||
|
||||
self.view.isUserInteractionEnabled = true
|
||||
|
||||
let brushGestureRecognizer = ImageEditorPanGestureRecognizer(target: self, action: #selector(handleBrushGesture(_:)))
|
||||
brushGestureRecognizer.maximumNumberOfTouches = 1
|
||||
brushGestureRecognizer.referenceView = canvasView.gestureReferenceView
|
||||
self.view.addGestureRecognizer(brushGestureRecognizer)
|
||||
self.brushGestureRecognizer = brushGestureRecognizer
|
||||
|
||||
updateNavigationBar()
|
||||
}
|
||||
|
||||
public override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
self.view.layoutSubviews()
|
||||
}
|
||||
|
||||
public override func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
self.view.layoutSubviews()
|
||||
}
|
||||
|
||||
public func updateNavigationBar() {
|
||||
let undoButton = navigationBarButton(imageName: "image_editor_undo",
|
||||
selector: #selector(didTapUndo(sender:)))
|
||||
let doneButton = navigationBarButton(imageName: "image_editor_checkmark_full",
|
||||
selector: #selector(didTapDone(sender:)))
|
||||
|
||||
var navigationBarItems = [UIView]()
|
||||
if model.canUndo() {
|
||||
navigationBarItems = [undoButton, doneButton]
|
||||
} else {
|
||||
navigationBarItems = [doneButton]
|
||||
}
|
||||
updateNavigationBar(navigationBarItems: navigationBarItems)
|
||||
}
|
||||
|
||||
private var currentColor: UIColor {
|
||||
get {
|
||||
return paletteView.selectedColor
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Actions
|
||||
|
||||
@objc func didTapUndo(sender: UIButton) {
|
||||
Logger.verbose("")
|
||||
guard model.canUndo() else {
|
||||
owsFailDebug("Can't undo.")
|
||||
return
|
||||
}
|
||||
model.undo()
|
||||
}
|
||||
|
||||
@objc func didTapDone(sender: UIButton) {
|
||||
Logger.verbose("")
|
||||
|
||||
completeAndDismiss()
|
||||
}
|
||||
|
||||
private func completeAndDismiss() {
|
||||
self.delegate?.brushDidComplete()
|
||||
|
||||
self.dismiss(animated: false) {
|
||||
// Do nothing.
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Brush
|
||||
|
||||
// These properties are non-empty while drawing a stroke.
|
||||
private var currentStroke: ImageEditorStrokeItem?
|
||||
private var currentStrokeSamples = [ImageEditorStrokeItem.StrokeSample]()
|
||||
|
||||
@objc
|
||||
public func handleBrushGesture(_ gestureRecognizer: UIGestureRecognizer) {
|
||||
AssertIsOnMainThread()
|
||||
|
||||
let removeCurrentStroke = {
|
||||
if let stroke = self.currentStroke {
|
||||
self.model.remove(item: stroke)
|
||||
}
|
||||
self.currentStroke = nil
|
||||
self.currentStrokeSamples.removeAll()
|
||||
}
|
||||
let tryToAppendStrokeSample = {
|
||||
let view = self.canvasView.gestureReferenceView
|
||||
let viewBounds = view.bounds
|
||||
let locationInView = gestureRecognizer.location(in: view)
|
||||
let newSample = ImageEditorCanvasView.locationImageUnit(forLocationInView: locationInView,
|
||||
viewBounds: viewBounds,
|
||||
model: self.model,
|
||||
transform: self.model.currentTransform())
|
||||
|
||||
if let prevSample = self.currentStrokeSamples.last,
|
||||
prevSample == newSample {
|
||||
// Ignore duplicate samples.
|
||||
return
|
||||
}
|
||||
self.currentStrokeSamples.append(newSample)
|
||||
}
|
||||
|
||||
let strokeColor = currentColor
|
||||
// TODO: Tune stroke width.
|
||||
let unitStrokeWidth = ImageEditorStrokeItem.defaultUnitStrokeWidth()
|
||||
|
||||
switch gestureRecognizer.state {
|
||||
case .began:
|
||||
removeCurrentStroke()
|
||||
|
||||
tryToAppendStrokeSample()
|
||||
|
||||
let stroke = ImageEditorStrokeItem(color: strokeColor, unitSamples: currentStrokeSamples, unitStrokeWidth: unitStrokeWidth)
|
||||
model.append(item: stroke)
|
||||
currentStroke = stroke
|
||||
|
||||
case .changed, .ended:
|
||||
tryToAppendStrokeSample()
|
||||
|
||||
guard let lastStroke = self.currentStroke else {
|
||||
owsFailDebug("Missing last stroke.")
|
||||
removeCurrentStroke()
|
||||
return
|
||||
}
|
||||
|
||||
// Model items are immutable; we _replace_ the
|
||||
// stroke item rather than modify it.
|
||||
let stroke = ImageEditorStrokeItem(itemId: lastStroke.itemId, color: strokeColor, unitSamples: currentStrokeSamples, unitStrokeWidth: unitStrokeWidth)
|
||||
model.replace(item: stroke, suppressUndo: true)
|
||||
|
||||
if gestureRecognizer.state == .ended {
|
||||
currentStroke = nil
|
||||
currentStrokeSamples.removeAll()
|
||||
} else {
|
||||
currentStroke = stroke
|
||||
}
|
||||
default:
|
||||
removeCurrentStroke()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
extension ImageEditorBrushViewController: ImageEditorModelObserver {
|
||||
|
||||
public func imageEditorModelDidChange(before: ImageEditorContents,
|
||||
after: ImageEditorContents) {
|
||||
updateNavigationBar()
|
||||
}
|
||||
|
||||
public func imageEditorModelDidChange(changedItemIds: [String]) {
|
||||
updateNavigationBar()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
extension ImageEditorBrushViewController: ImageEditorPaletteViewDelegate {
|
||||
public func selectedColorDidChange() {
|
||||
// TODO:
|
||||
}
|
||||
}
|
|
@ -59,7 +59,7 @@ public class ImageEditorCanvasView: UIView {
|
|||
private var imageLayer = CALayer()
|
||||
|
||||
@objc
|
||||
public func configureSubviews() -> Bool {
|
||||
public func configureSubviews() {
|
||||
self.backgroundColor = .clear
|
||||
self.isOpaque = false
|
||||
|
||||
|
@ -94,8 +94,6 @@ public class ImageEditorCanvasView: UIView {
|
|||
contentView.autoPinEdgesToSuperviewEdges()
|
||||
|
||||
updateLayout()
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
public var gestureReferenceView: UIView {
|
||||
|
@ -631,6 +629,19 @@ public class ImageEditorCanvasView: UIView {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MARK: - Coordinates
|
||||
|
||||
public class func locationImageUnit(forLocationInView locationInView: CGPoint,
|
||||
viewBounds: CGRect,
|
||||
model: ImageEditorModel,
|
||||
transform: ImageEditorTransform) -> CGPoint {
|
||||
let imageFrame = self.imageFrame(forViewSize: viewBounds.size, imageSize: model.srcImageSizePixels, transform: transform)
|
||||
let affineTransformStart = transform.affineTransform(viewSize: viewBounds.size)
|
||||
let locationInContent = locationInView.minus(viewBounds.center).applyingInverse(affineTransformStart).plus(viewBounds.center)
|
||||
let locationImageUnit = locationInContent.toUnitCoordinates(viewBounds: imageFrame, shouldClamp: false)
|
||||
return locationImageUnit
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
|
|
@ -738,7 +738,7 @@ class ImageEditorCropViewController: OWSViewController {
|
|||
private func completeAndDismiss() {
|
||||
self.delegate?.cropDidComplete(transform: transform)
|
||||
|
||||
self.dismiss(animated: true) {
|
||||
self.dismiss(animated: false) {
|
||||
// Do nothing.
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ public class ImageEditorPaletteView: UIView {
|
|||
private func createContents() {
|
||||
self.backgroundColor = .clear
|
||||
self.isOpaque = false
|
||||
self.layoutMargins = .zero
|
||||
|
||||
if let image = ImageEditorPaletteView.buildPaletteGradientImage() {
|
||||
imageView.image = image
|
||||
|
|
|
@ -204,7 +204,7 @@ public class ImageEditorTextViewController: OWSViewController, VAlignTextViewDel
|
|||
|
||||
self.delegate?.textEditDidComplete(textItem: textItem, text: textView.text)
|
||||
|
||||
self.dismiss(animated: true) {
|
||||
self.dismiss(animated: false) {
|
||||
// Do nothing.
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,9 +75,7 @@ public class ImageEditorView: UIView {
|
|||
|
||||
@objc
|
||||
public func configureSubviews() -> Bool {
|
||||
guard canvasView.configureSubviews() else {
|
||||
return false
|
||||
}
|
||||
canvasView.configureSubviews()
|
||||
self.addSubview(canvasView)
|
||||
canvasView.autoPinEdgesToSuperviewEdges()
|
||||
|
||||
|
@ -241,18 +239,6 @@ public class ImageEditorView: UIView {
|
|||
|
||||
// MARK: - Navigation Bar
|
||||
|
||||
private func navigationBarButton(imageName: String,
|
||||
selector: Selector) -> UIView {
|
||||
let button = OWSButton()
|
||||
button.setImage(imageName: imageName)
|
||||
button.tintColor = .white
|
||||
button.addTarget(self, action: selector, for: .touchUpInside)
|
||||
// button.layer.shadowColor = UIColor.black.cgColor
|
||||
// button.layer.shadowRadius = 4
|
||||
// button.layer.shadowOpacity = 0.66
|
||||
return button
|
||||
}
|
||||
|
||||
public func navigationBarItems() -> [UIView] {
|
||||
let undoButton = navigationBarButton(imageName: "image_editor_undo",
|
||||
selector: #selector(didTapUndo(sender:)))
|
||||
|
@ -294,6 +280,10 @@ public class ImageEditorView: UIView {
|
|||
Logger.verbose("")
|
||||
|
||||
self.editorMode = .brush
|
||||
|
||||
let brushView = ImageEditorBrushViewController(delegate: self, model: model)
|
||||
self.delegate?.imageEditor(presentFullScreenOverlay: brushView,
|
||||
withNavigation: true)
|
||||
}
|
||||
|
||||
@objc func didTapCrop(sender: UIButton) {
|
||||
|
@ -425,11 +415,11 @@ public class ImageEditorView: UIView {
|
|||
let viewBounds = view.bounds
|
||||
let locationStart = gestureRecognizer.pinchStateStart.centroid
|
||||
let locationNow = gestureRecognizer.pinchStateLast.centroid
|
||||
let gestureStartImageUnit = ImageEditorView.locationImageUnit(forLocationInView: locationStart,
|
||||
let gestureStartImageUnit = ImageEditorCanvasView.locationImageUnit(forLocationInView: locationStart,
|
||||
viewBounds: viewBounds,
|
||||
model: self.model,
|
||||
transform: self.model.currentTransform())
|
||||
let gestureNowImageUnit = ImageEditorView.locationImageUnit(forLocationInView: locationNow,
|
||||
let gestureNowImageUnit = ImageEditorCanvasView.locationImageUnit(forLocationInView: locationNow,
|
||||
viewBounds: viewBounds,
|
||||
model: self.model,
|
||||
transform: self.model.currentTransform())
|
||||
|
@ -516,11 +506,11 @@ public class ImageEditorView: UIView {
|
|||
let view = self.canvasView.gestureReferenceView
|
||||
let viewBounds = view.bounds
|
||||
let locationInView = gestureRecognizer.location(in: view)
|
||||
let gestureStartImageUnit = ImageEditorView.locationImageUnit(forLocationInView: locationStart,
|
||||
let gestureStartImageUnit = ImageEditorCanvasView.locationImageUnit(forLocationInView: locationStart,
|
||||
viewBounds: viewBounds,
|
||||
model: self.model,
|
||||
transform: self.model.currentTransform())
|
||||
let gestureNowImageUnit = ImageEditorView.locationImageUnit(forLocationInView: locationInView,
|
||||
let gestureNowImageUnit = ImageEditorCanvasView.locationImageUnit(forLocationInView: locationInView,
|
||||
viewBounds: viewBounds,
|
||||
model: self.model,
|
||||
transform: self.model.currentTransform())
|
||||
|
@ -564,7 +554,7 @@ public class ImageEditorView: UIView {
|
|||
let view = self.canvasView.gestureReferenceView
|
||||
let viewBounds = view.bounds
|
||||
let locationInView = gestureRecognizer.location(in: view)
|
||||
let newSample = ImageEditorView.locationImageUnit(forLocationInView: locationInView,
|
||||
let newSample = ImageEditorCanvasView.locationImageUnit(forLocationInView: locationInView,
|
||||
viewBounds: viewBounds,
|
||||
model: self.model,
|
||||
transform: self.model.currentTransform())
|
||||
|
@ -616,19 +606,6 @@ public class ImageEditorView: UIView {
|
|||
}
|
||||
}
|
||||
|
||||
// MARK: - Coordinates
|
||||
|
||||
private class func locationImageUnit(forLocationInView locationInView: CGPoint,
|
||||
viewBounds: CGRect,
|
||||
model: ImageEditorModel,
|
||||
transform: ImageEditorTransform) -> CGPoint {
|
||||
let imageFrame = ImageEditorCanvasView.imageFrame(forViewSize: viewBounds.size, imageSize: model.srcImageSizePixels, transform: transform)
|
||||
let affineTransformStart = transform.affineTransform(viewSize: viewBounds.size)
|
||||
let locationInContent = locationInView.minus(viewBounds.center).applyingInverse(affineTransformStart).plus(viewBounds.center)
|
||||
let locationImageUnit = locationInContent.toUnitCoordinates(viewBounds: imageFrame, shouldClamp: false)
|
||||
return locationImageUnit
|
||||
}
|
||||
|
||||
// MARK: - Edit Text Tool
|
||||
|
||||
private func edit(textItem: ImageEditorTextItem) {
|
||||
|
@ -760,3 +737,11 @@ extension ImageEditorView: ImageEditorPaletteViewDelegate {
|
|||
// TODO:
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
extension ImageEditorView: ImageEditorBrushViewControllerDelegate {
|
||||
public func brushDidComplete() {
|
||||
self.editorMode = .none
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
public extension NSObject {
|
||||
|
||||
public func navigationBarButton(imageName: String,
|
||||
selector: Selector) -> UIView {
|
||||
let button = OWSButton()
|
||||
button.setImage(imageName: imageName)
|
||||
button.tintColor = .white
|
||||
button.addTarget(self, action: selector, for: .touchUpInside)
|
||||
// button.layer.shadowColor = UIColor.black.cgColor
|
||||
// button.layer.shadowRadius = 4
|
||||
// button.layer.shadowOpacity = 0.66
|
||||
return button
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
public extension UIViewController {
|
||||
|
||||
public func updateNavigationBar(navigationBarItems: [UIView]) {
|
||||
guard navigationBarItems.count > 0 else {
|
||||
self.navigationItem.rightBarButtonItems = []
|
||||
return
|
||||
}
|
||||
|
||||
let stackView = UIStackView(arrangedSubviews: navigationBarItems)
|
||||
stackView.axis = .horizontal
|
||||
stackView.spacing = 8
|
||||
stackView.alignment = .center
|
||||
|
||||
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: stackView)
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue