|
|
|
@ -29,12 +29,14 @@ public class ImageEditorView: UIView {
|
|
|
|
|
// This is the default mode. It is used for interacting with text items.
|
|
|
|
|
case none
|
|
|
|
|
case brush
|
|
|
|
|
case text
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private var editorMode = EditorMode.none {
|
|
|
|
|
didSet {
|
|
|
|
|
AssertIsOnMainThread()
|
|
|
|
|
|
|
|
|
|
updateButtons()
|
|
|
|
|
updateGestureState()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -130,15 +132,18 @@ public class ImageEditorView: UIView {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The model supports redo if we ever want to add it.
|
|
|
|
|
private let undoButton = UIButton(type: .custom)
|
|
|
|
|
private let brushButton = UIButton(type: .custom)
|
|
|
|
|
private let cropButton = UIButton(type: .custom)
|
|
|
|
|
private let newTextButton = UIButton(type: .custom)
|
|
|
|
|
private var allButtons = [UIButton]()
|
|
|
|
|
private let undoButton = OWSButton()
|
|
|
|
|
private let brushButton = OWSButton()
|
|
|
|
|
private let cropButton = OWSButton()
|
|
|
|
|
private let newTextButton = OWSButton()
|
|
|
|
|
private let captionButton = OWSButton()
|
|
|
|
|
private let doneButton = OWSButton()
|
|
|
|
|
private let buttonStackView = UIStackView()
|
|
|
|
|
|
|
|
|
|
// TODO: Should this method be private?
|
|
|
|
|
@objc
|
|
|
|
|
public func addControls(to containerView: UIView) {
|
|
|
|
|
public func addControls(to containerView: UIView,
|
|
|
|
|
viewController: UIViewController) {
|
|
|
|
|
configure(button: undoButton,
|
|
|
|
|
imageName: "image_editor_undo",
|
|
|
|
|
selector: #selector(didTapUndo(sender:)))
|
|
|
|
@ -155,16 +160,21 @@ public class ImageEditorView: UIView {
|
|
|
|
|
imageName: "image_editor_text",
|
|
|
|
|
selector: #selector(didTapNewText(sender:)))
|
|
|
|
|
|
|
|
|
|
allButtons = [brushButton, cropButton, undoButton, newTextButton]
|
|
|
|
|
configure(button: captionButton,
|
|
|
|
|
imageName: "image_editor_caption",
|
|
|
|
|
selector: #selector(didTapCaption(sender:)))
|
|
|
|
|
|
|
|
|
|
configure(button: doneButton,
|
|
|
|
|
imageName: "image_editor_checkmark_full",
|
|
|
|
|
selector: #selector(didTapDone(sender:)))
|
|
|
|
|
|
|
|
|
|
let stackView = UIStackView(arrangedSubviews: allButtons)
|
|
|
|
|
stackView.axis = .vertical
|
|
|
|
|
stackView.alignment = .center
|
|
|
|
|
stackView.spacing = 10
|
|
|
|
|
buttonStackView.axis = .horizontal
|
|
|
|
|
buttonStackView.alignment = .center
|
|
|
|
|
buttonStackView.spacing = 20
|
|
|
|
|
|
|
|
|
|
containerView.addSubview(stackView)
|
|
|
|
|
stackView.autoAlignAxis(toSuperviewAxis: .horizontal)
|
|
|
|
|
stackView.autoPinTrailingToSuperviewMargin(withInset: 10)
|
|
|
|
|
containerView.addSubview(buttonStackView)
|
|
|
|
|
buttonStackView.autoPin(toTopLayoutGuideOf: viewController, withInset: 0)
|
|
|
|
|
buttonStackView.autoPinTrailingToSuperviewMargin(withInset: 18)
|
|
|
|
|
|
|
|
|
|
containerView.addSubview(paletteView)
|
|
|
|
|
paletteView.autoVCenterInSuperview()
|
|
|
|
@ -182,10 +192,6 @@ public class ImageEditorView: UIView {
|
|
|
|
|
owsFailDebug("Missing asset: \(imageName)")
|
|
|
|
|
}
|
|
|
|
|
button.tintColor = .white
|
|
|
|
|
button.setTitleColor(.white, for: .normal)
|
|
|
|
|
button.setTitleColor(.gray, for: .disabled)
|
|
|
|
|
button.setTitleColor(UIColor.ows_materialBlue, for: .selected)
|
|
|
|
|
button.titleLabel?.font = UIFont.ows_dynamicTypeBody.ows_mediumWeight()
|
|
|
|
|
button.addTarget(self, action: selector, for: .touchUpInside)
|
|
|
|
|
button.layer.shadowColor = UIColor.black.cgColor
|
|
|
|
|
button.layer.shadowRadius = 4
|
|
|
|
@ -193,14 +199,39 @@ public class ImageEditorView: UIView {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private func updateButtons() {
|
|
|
|
|
undoButton.isEnabled = model.canUndo()
|
|
|
|
|
brushButton.isSelected = editorMode == .brush
|
|
|
|
|
cropButton.isSelected = false
|
|
|
|
|
newTextButton.isSelected = false
|
|
|
|
|
var buttons = [OWSButton]()
|
|
|
|
|
|
|
|
|
|
var hasPalette = false
|
|
|
|
|
switch editorMode {
|
|
|
|
|
case .text:
|
|
|
|
|
// TODO:
|
|
|
|
|
hasPalette = true
|
|
|
|
|
break
|
|
|
|
|
case .brush:
|
|
|
|
|
hasPalette = true
|
|
|
|
|
|
|
|
|
|
if model.canUndo() {
|
|
|
|
|
buttons = [undoButton, doneButton]
|
|
|
|
|
} else {
|
|
|
|
|
buttons = [doneButton]
|
|
|
|
|
}
|
|
|
|
|
case .none:
|
|
|
|
|
if model.canUndo() {
|
|
|
|
|
buttons = [undoButton, newTextButton, brushButton, cropButton, captionButton]
|
|
|
|
|
} else {
|
|
|
|
|
buttons = [newTextButton, brushButton, cropButton, captionButton]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for button in allButtons {
|
|
|
|
|
button.isHidden = isEditingTextItem
|
|
|
|
|
for subview in buttonStackView.subviews {
|
|
|
|
|
subview.removeFromSuperview()
|
|
|
|
|
}
|
|
|
|
|
buttonStackView.addArrangedSubview(UIView.hStretchingSpacer())
|
|
|
|
|
for button in buttons {
|
|
|
|
|
buttonStackView.addArrangedSubview(button)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
paletteView.isHidden = !hasPalette
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MARK: - Actions
|
|
|
|
@ -217,7 +248,7 @@ public class ImageEditorView: UIView {
|
|
|
|
|
@objc func didTapBrush(sender: UIButton) {
|
|
|
|
|
Logger.verbose("")
|
|
|
|
|
|
|
|
|
|
toggle(editorMode: .brush)
|
|
|
|
|
self.editorMode = .brush
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@objc func didTapCrop(sender: UIButton) {
|
|
|
|
@ -244,13 +275,16 @@ public class ImageEditorView: UIView {
|
|
|
|
|
edit(textItem: textItem)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func toggle(editorMode: EditorMode) {
|
|
|
|
|
if self.editorMode == editorMode {
|
|
|
|
|
self.editorMode = .none
|
|
|
|
|
} else {
|
|
|
|
|
self.editorMode = editorMode
|
|
|
|
|
}
|
|
|
|
|
updateButtons()
|
|
|
|
|
@objc func didTapCaption(sender: UIButton) {
|
|
|
|
|
Logger.verbose("")
|
|
|
|
|
|
|
|
|
|
// TODO:
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@objc func didTapDone(sender: UIButton) {
|
|
|
|
|
Logger.verbose("")
|
|
|
|
|
|
|
|
|
|
self.editorMode = .none
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MARK: - Gestures
|
|
|
|
@ -270,6 +304,11 @@ public class ImageEditorView: UIView {
|
|
|
|
|
brushGestureRecognizer?.isEnabled = true
|
|
|
|
|
tapGestureRecognizer?.isEnabled = false
|
|
|
|
|
pinchGestureRecognizer?.isEnabled = false
|
|
|
|
|
case .text:
|
|
|
|
|
moveTextGestureRecognizer?.isEnabled = false
|
|
|
|
|
brushGestureRecognizer?.isEnabled = false
|
|
|
|
|
tapGestureRecognizer?.isEnabled = false
|
|
|
|
|
pinchGestureRecognizer?.isEnabled = false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -537,20 +576,10 @@ public class ImageEditorView: UIView {
|
|
|
|
|
|
|
|
|
|
// MARK: - Edit Text Tool
|
|
|
|
|
|
|
|
|
|
private var isEditingTextItem = false {
|
|
|
|
|
didSet {
|
|
|
|
|
AssertIsOnMainThread()
|
|
|
|
|
|
|
|
|
|
updateButtons()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private func edit(textItem: ImageEditorTextItem) {
|
|
|
|
|
Logger.verbose("")
|
|
|
|
|
|
|
|
|
|
toggle(editorMode: .none)
|
|
|
|
|
|
|
|
|
|
isEditingTextItem = true
|
|
|
|
|
self.editorMode = .text
|
|
|
|
|
|
|
|
|
|
// TODO:
|
|
|
|
|
let maxTextWidthPoints = model.srcImageSizePixels.width * ImageEditorTextItem.kDefaultUnitWidth
|
|
|
|
@ -566,7 +595,7 @@ public class ImageEditorView: UIView {
|
|
|
|
|
private func presentCropTool() {
|
|
|
|
|
Logger.verbose("")
|
|
|
|
|
|
|
|
|
|
toggle(editorMode: .none)
|
|
|
|
|
self.editorMode = .none
|
|
|
|
|
|
|
|
|
|
guard let srcImage = canvasView.loadSrcImage() else {
|
|
|
|
|
owsFailDebug("Couldn't load src image.")
|
|
|
|
@ -628,7 +657,7 @@ extension ImageEditorView: ImageEditorTextViewControllerDelegate {
|
|
|
|
|
public func textEditDidComplete(textItem: ImageEditorTextItem, text: String?) {
|
|
|
|
|
AssertIsOnMainThread()
|
|
|
|
|
|
|
|
|
|
isEditingTextItem = false
|
|
|
|
|
self.editorMode = .none
|
|
|
|
|
|
|
|
|
|
guard let text = text?.ows_stripped(),
|
|
|
|
|
text.count > 0 else {
|
|
|
|
@ -648,7 +677,7 @@ extension ImageEditorView: ImageEditorTextViewControllerDelegate {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public func textEditDidCancel() {
|
|
|
|
|
isEditingTextItem = false
|
|
|
|
|
self.editorMode = .none
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|