Skip to content

Commit 473a513

Browse files
committed
Collapsed Colors, Clean Up and Document
1 parent b5092fe commit 473a513

File tree

3 files changed

+76
-48
lines changed

3 files changed

+76
-48
lines changed

Sources/CodeEditSourceEditor/LineFolding/View/FoldingRibbonView+Draw.swift

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ extension FoldingRibbonView {
1515
let endLine: TextLineStorage<TextLine>.TextLinePosition
1616
}
1717

18+
// MARK: - Draw
19+
1820
override func draw(_ dirtyRect: NSRect) {
1921
guard let context = NSGraphicsContext.current?.cgContext,
2022
let layoutManager = model?.controller?.textView.layoutManager else {
@@ -53,6 +55,20 @@ extension FoldingRibbonView {
5355
context.restoreGState()
5456
}
5557

58+
// MARK: - Get Drawing Folds
59+
60+
/// Generates drawable fold info for a range of text.
61+
///
62+
/// The fold storage intentionally does not store the full ranges of all folds at each interval. We may, for an
63+
/// interval, find that we only receive fold information for depths > 1. In this case, we still need to draw those
64+
/// layers of color to create the illusion that those folds are continuous under the nested folds. To achieve this,
65+
/// we create 'fake' folds that span more than the queried text range. When returned for drawing, the drawing
66+
/// methods will draw those extra folds normally.
67+
///
68+
/// - Parameters:
69+
/// - textRange: The range of characters in text to create drawing fold info for.
70+
/// - layoutManager: A layout manager to query for line layout information.
71+
/// - Returns: A list of folds to draw for the given text range.
5672
private func getDrawingFolds(
5773
forTextRange textRange: Range<Int>,
5874
layoutManager: TextLayoutManager
@@ -123,6 +139,8 @@ extension FoldingRibbonView {
123139
}
124140
}
125141

142+
// MARK: - Collapsed Fold
143+
126144
private func drawCollapsedFold(
127145
minYPosition: CGFloat,
128146
maxYPosition: CGFloat,
@@ -144,19 +162,21 @@ extension FoldingRibbonView {
144162
chevron.addLine(to: CGPoint(x: maxX, y: centerY))
145163
chevron.addLine(to: CGPoint(x: minX, y: maxY))
146164

147-
context.setStrokeColor(NSColor.secondaryLabelColor.cgColor)
165+
context.setStrokeColor(foldedIndicatorChevronColor)
148166
context.setLineCap(.round)
149167
context.setLineJoin(.round)
150168
context.setLineWidth(1.3)
151169

152-
context.setFillColor(NSColor.tertiaryLabelColor.cgColor)
170+
context.setFillColor(foldedIndicatorColor)
153171
context.fill(fillRect)
154172
context.addPath(chevron)
155173
context.strokePath()
156174

157175
context.restoreGState()
158176
}
159177

178+
// MARK: - Hovered Fold
179+
160180
private func drawHoveredFold(
161181
minYPosition: CGFloat,
162182
maxYPosition: CGFloat,
@@ -203,6 +223,8 @@ extension FoldingRibbonView {
203223
context.restoreGState()
204224
}
205225

226+
// MARK: - Nested Fold
227+
206228
private func drawNestedFold(
207229
foldInfo: DrawingFoldInfo,
208230
foldCaps: FoldCapInfo,
@@ -241,6 +263,8 @@ extension FoldingRibbonView {
241263
context.restoreGState()
242264
}
243265

266+
// MARK: - Nested Outline
267+
244268
/// Draws a rounded outline for a rectangle, creating the small, light, outline around each fold indicator.
245269
///
246270
/// This function does not change fill colors for the given context.

Sources/CodeEditSourceEditor/LineFolding/View/FoldingRibbonView+FoldCapInfo.swift

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
import AppKit
99

1010
extension FoldingRibbonView {
11+
/// A helper type that determines if a fold should be drawn with a cap on the top or bottom if
12+
/// there's an adjacent fold on the same text line. It also provides a helper method
1113
struct FoldCapInfo {
1214
let startIndices: Set<Int>
1315
let endIndices: Set<Int>
@@ -32,13 +34,15 @@ extension FoldingRibbonView {
3234
let capTop = foldNeedsTopCap(fold)
3335
let capBottom = foldNeedsBottomCap(fold)
3436
let yDelta = capTop ? fold.startLine.height / 2.0 : 0.0
35-
let heightDelta: CGFloat = if capTop && capBottom {
36-
-fold.startLine.height
37-
} else if capTop || capBottom {
38-
-(fold.startLine.height / 2.0)
39-
} else {
40-
0.0
37+
38+
var heightDelta: CGFloat = 0.0
39+
if capTop {
40+
heightDelta -= fold.startLine.height / 2.0
41+
}
42+
if capBottom {
43+
heightDelta -= fold.endLine.height / 2.0
4144
}
45+
4246
return NSRect(
4347
x: rect.origin.x,
4448
y: rect.origin.y + yDelta,

Sources/CodeEditSourceEditor/LineFolding/View/FoldingRibbonView.swift

Lines changed: 40 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,21 @@ import AppKit
1010
import CodeEditTextView
1111
import Combine
1212

13+
extension NSColor {
14+
convenience init(light: NSColor, dark: NSColor) {
15+
self.init(name: nil) { appearance in
16+
return switch appearance.name {
17+
case .aqua:
18+
light
19+
case .darkAqua:
20+
dark
21+
default:
22+
NSColor()
23+
}
24+
}
25+
}
26+
}
27+
1328
/// Displays the code folding ribbon in the ``GutterView``.
1429
///
1530
/// This view draws its contents
@@ -33,52 +48,37 @@ class FoldingRibbonView: NSView {
3348
var backgroundColor: NSColor = NSColor.controlBackgroundColor
3449

3550
@Invalidating(.display)
36-
var markerColor = NSColor(name: nil) { appearance in
37-
return switch appearance.name {
38-
case .aqua:
39-
NSColor(deviceWhite: 0.0, alpha: 0.1)
40-
case .darkAqua:
41-
NSColor(deviceWhite: 1.0, alpha: 0.2)
42-
default:
43-
NSColor()
44-
}
45-
}.cgColor
51+
var markerColor = NSColor(
52+
light: NSColor(deviceWhite: 0.0, alpha: 0.1),
53+
dark: NSColor(deviceWhite: 1.0, alpha: 0.2)
54+
).cgColor
4655

4756
@Invalidating(.display)
48-
var markerBorderColor = NSColor(name: nil) { appearance in
49-
return switch appearance.name {
50-
case .aqua:
51-
NSColor(deviceWhite: 1.0, alpha: 0.4)
52-
case .darkAqua:
53-
NSColor(deviceWhite: 0.0, alpha: 0.4)
54-
default:
55-
NSColor()
56-
}
57-
}.cgColor
57+
var markerBorderColor = NSColor(
58+
light: NSColor(deviceWhite: 1.0, alpha: 0.4),
59+
dark: NSColor(deviceWhite: 0.0, alpha: 0.4)
60+
).cgColor
5861

5962
@Invalidating(.display)
60-
var hoverFillColor = NSColor(name: nil) { appearance in
61-
return switch appearance.name {
62-
case .aqua:
63-
NSColor(deviceWhite: 1.0, alpha: 1.0)
64-
case .darkAqua:
65-
NSColor(deviceWhite: 0.17, alpha: 1.0)
66-
default:
67-
NSColor()
68-
}
69-
}.cgColor
63+
var hoverFillColor = NSColor(
64+
light: NSColor(deviceWhite: 1.0, alpha: 1.0),
65+
dark: NSColor(deviceWhite: 0.17, alpha: 1.0)
66+
).cgColor
7067

7168
@Invalidating(.display)
72-
var hoverBorderColor = NSColor(name: nil) { appearance in
73-
return switch appearance.name {
74-
case .aqua:
75-
NSColor(deviceWhite: 0.8, alpha: 1.0)
76-
case .darkAqua:
77-
NSColor(deviceWhite: 0.4, alpha: 1.0)
78-
default:
79-
NSColor()
80-
}
81-
}.cgColor
69+
var hoverBorderColor = NSColor(
70+
light: NSColor(deviceWhite: 0.8, alpha: 1.0),
71+
dark: NSColor(deviceWhite: 0.4, alpha: 1.0)
72+
).cgColor
73+
74+
@Invalidating(.display)
75+
var foldedIndicatorColor = NSColor(
76+
light: NSColor(deviceWhite: 0.0, alpha: 0.3),
77+
dark: NSColor(deviceWhite: 1.0, alpha: 0.6)
78+
).cgColor
79+
80+
@Invalidating(.display)
81+
var foldedIndicatorChevronColor = NSColor.secondaryLabelColor.cgColor
8282

8383
override public var isFlipped: Bool {
8484
true

0 commit comments

Comments
 (0)