Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class GenericElementConverter: ElementConverter {

// MARK: - Built-in formatter instances

lazy var blockquoteFormatter = BlockquoteFormatter()
lazy var blockquoteFormatter = BlockquoteFormatter(increaseDepth: true)
lazy var boldFormatter = BoldFormatter()
lazy var divFormatter = HTMLDivFormatter()
lazy var h1Formatter = HeaderFormatter(headerLevel: .h1)
Expand Down
71 changes: 65 additions & 6 deletions Aztec/Classes/Formatters/Implementations/BlockquoteFormatter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,55 @@ import UIKit
//
class BlockquoteFormatter: ParagraphAttributeFormatter {

typealias TextAttributes = [NSAttributedString.Key: Any]?

/// Attributes to be added by default
///
let placeholderAttributes: [NSAttributedString.Key: Any]?

let typingAttributes: TextAttributes

let defaultTextAttributes: TextAttributes
let borderColors: [UIColor]?

/// Tells if the formatter is increasing the depth of a blockquote or simple changing the current one if any
let increaseDepth: Bool

let currentDepth: Int

/// Designated Initializer
///
init(placeholderAttributes: [NSAttributedString.Key: Any]? = nil) {
self.placeholderAttributes = placeholderAttributes
init(typingAttributes: TextAttributes = nil, defaultTextAttributes: TextAttributes = nil, borderColors: [UIColor]? = nil, increaseDepth: Bool = false, currentDepth: Int = 0) {
self.typingAttributes = typingAttributes
self.defaultTextAttributes = defaultTextAttributes
self.borderColors = borderColors
self.increaseDepth = increaseDepth

self.currentDepth = typingAttributes?.paragraphStyle().blockquoteDepth ?? 0
}

private func colorForNext(depth: Int) -> UIColor {
guard let colors = borderColors else { return UIColor.darkText }

if increaseDepth {
let index = min(depth+1, colors.count-1)
return colors[index]
} else {
return colors[0]
}
}

private func colorForPrev(depth: Int) -> UIColor {
guard let colors = borderColors else { return UIColor.darkText }

//increaseDepth is not used here as shift tab and pressing quote toggle button behave differently
if depth > 0 {
let positiveIndex = max(depth-1, 0)
let index = min(positiveIndex, colors.count-1)
return colors[index]
} else {
guard let att = defaultTextAttributes else { return UIColor.darkText }
return att[.foregroundColor] as! UIColor
}
}

// MARK: - Overwriten Methods

Expand All @@ -26,11 +64,20 @@ class BlockquoteFormatter: ParagraphAttributeFormatter {
if let paragraphStyle = attributes[.paragraphStyle] as? NSParagraphStyle {
newParagraphStyle.setParagraphStyle(paragraphStyle)
}

newParagraphStyle.appendProperty(Blockquote(with: representation))

let newQuote = Blockquote(with: representation)

if newParagraphStyle.blockquotes.isEmpty || increaseDepth {
newParagraphStyle.insertProperty(newQuote, afterLastOfType: Blockquote.self)
} else {
newParagraphStyle.replaceProperty(ofType: Blockquote.self, with: newQuote)
}

var resultingAttributes = attributes
resultingAttributes[.paragraphStyle] = newParagraphStyle
resultingAttributes[.foregroundColor] = colorForNext(depth: currentDepth)


return resultingAttributes
}

Expand All @@ -47,6 +94,13 @@ class BlockquoteFormatter: ParagraphAttributeFormatter {

var resultingAttributes = attributes
resultingAttributes[.paragraphStyle] = newParagraphStyle

//remove quote color
resultingAttributes.removeValue(forKey: .foregroundColor)

resultingAttributes[.foregroundColor] = colorForPrev(depth: currentDepth)


return resultingAttributes
}

Expand All @@ -56,4 +110,9 @@ class BlockquoteFormatter: ParagraphAttributeFormatter {
}
return !style.blockquotes.isEmpty
}

static func blockquotes(in attributes: [NSAttributedString.Key: Any]) -> [Blockquote] {
let style = attributes[.paragraphStyle] as? ParagraphStyle
return style?.blockquotes ?? []
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class TextListFormatter: ParagraphAttributeFormatter {
}

let newList = TextList(style: self.listStyle, with: representation)

if newParagraphStyle.lists.isEmpty || increaseDepth {
newParagraphStyle.insertProperty(newList, afterLastOfType: HTMLLi.self)
} else {
Expand Down
58 changes: 39 additions & 19 deletions Aztec/Classes/TextKit/LayoutManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@ import QuartzCore
class LayoutManager: NSLayoutManager {

/// Blockquote's Left Border Color
///
var blockquoteBorderColor: UIColor? = UIColor(red: 0.52, green: 0.65, blue: 0.73, alpha: 1.0)
/// Set the array with how many colors you like, they appear in the order they are set in the array.
var blockquoteBorderColors = [UIColor(hexString: "9252FF")!,
UIColor(hexString: "5A4AE8")!,
UIColor(hexString: "5D77FE")!,
UIColor(hexString: "4A8EE8")!,
UIColor(hexString: "52CAFF")!]

/// Blockquote's Background Color
///
Expand Down Expand Up @@ -62,17 +66,27 @@ private extension LayoutManager {
guard let paragraphStyle = object as? ParagraphStyle, !paragraphStyle.blockquotes.isEmpty else {
return
}

let blockquoteIndent = paragraphStyle.blockquoteIndent

let blockquoteGlyphRange = glyphRange(forCharacterRange: range, actualCharacterRange: nil)

enumerateLineFragments(forGlyphRange: blockquoteGlyphRange) { (rect, usedRect, textContainer, glyphRange, stop) in
let lineRange = self.characterRange(forGlyphRange: glyphRange, actualGlyphRange: nil)
let lineCharacters = textStorage.attributedSubstring(from: lineRange).string
let lineEndsParagraph = lineCharacters.isEndOfParagraph(before: lineCharacters.endIndex)
let blockquoteRect = self.blockquoteRect(origin: origin, lineRect: rect, blockquoteIndent: blockquoteIndent, lineEndsParagraph: lineEndsParagraph)
let blockquoteRect = self.blockquoteRect(origin: origin, lineRect: rect, blockquoteIndent: 0.0, lineEndsParagraph: lineEndsParagraph)

self.drawBlockquoteBackground(in: blockquoteRect.integral, with: context)

let nestDepth = paragraphStyle.blockquoteDepth
for index in 0...nestDepth {
let indent = CGFloat(index) * Metrics.listTextIndentation

let nestRect = self.blockquoteRect(origin: origin, lineRect: rect, blockquoteIndent: indent, lineEndsParagraph: lineEndsParagraph)

self.drawBlockquote(in: blockquoteRect.integral, with: context)
self.drawBlockquoteBorder(in: nestRect.integral, with: context, at: index)
}


}
}

Expand All @@ -90,7 +104,8 @@ private extension LayoutManager {
let extraIndent = paragraphStyle.blockquoteIndent
let extraRect = blockquoteRect(origin: origin, lineRect: extraLineFragmentRect, blockquoteIndent: extraIndent, lineEndsParagraph: false)

drawBlockquote(in: extraRect.integral, with: context)
drawBlockquoteBackground(in: extraRect.integral, with: context)
drawBlockquoteBorder(in: extraRect.integral, with: context, at: 0)
}


Expand Down Expand Up @@ -122,21 +137,26 @@ private extension LayoutManager {

return blockquoteRect
}

private func drawBlockquoteBorder(in rect: CGRect, with context: CGContext, at depth: Int) {
let quoteCount = blockquoteBorderColors.count
let index = min(depth, quoteCount-1)

guard index < quoteCount else {return}

let borderColor = blockquoteBorderColors[index]
let borderRect = CGRect(origin: rect.origin, size: CGSize(width: blockquoteBorderWidth, height: rect.height))
borderColor.setFill()
context.fill(borderRect)
}

/// Draws a single Blockquote Line Fragment, in the specified Rectangle, using a given Graphics Context.
///
private func drawBlockquote(in rect: CGRect, with context: CGContext) {
if let blockquoteBackgroundColor = blockquoteBackgroundColor {
blockquoteBackgroundColor.setFill()
context.fill(rect)

}

if let blockquoteBorderColor = blockquoteBorderColor {
let borderRect = CGRect(origin: rect.origin, size: CGSize(width: blockquoteBorderWidth, height: rect.height))
blockquoteBorderColor.setFill()
context.fill(borderRect)
}
private func drawBlockquoteBackground(in rect: CGRect, with context: CGContext) {
guard let color = blockquoteBackgroundColor else {return}

color.setFill()
context.fill(rect)
}
}

Expand Down
26 changes: 16 additions & 10 deletions Aztec/Classes/TextKit/ParagraphStyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -175,21 +175,27 @@ open class ParagraphStyle: NSMutableParagraphStyle, CustomReflectable {
super.tailIndent = newValue
}
}

/// The amount of indent for the blockquote of the paragraph if any.
/// The amount of indent for the nested blockquote of the paragraph if any.
///
public var blockquoteIndent: CGFloat {
let blockquoteIndex = properties.filter({ property in
return CGFloat(blockquoteDepth) * Metrics.listTextIndentation
}

/// The level of depth for the nested blockquote of the paragraph if any.
///
public var blockquoteDepth: Int {
let listAndBlockquotes = properties.filter({ property in
return property is Blockquote || property is TextList
}).firstIndex(where: { property in
return property is Blockquote
})

guard let depth = blockquoteIndex else {
return 0
var depth = 0
for position in (0..<listAndBlockquotes.count).reversed() {
if listAndBlockquotes[position] is Blockquote {
depth = position
break
}
}

return CGFloat(depth) * Metrics.listTextIndentation
return depth
}

/// The amount of indent for the list of the paragraph if any.
Expand Down
Loading