77
88import AppKit
99
10- class IssueTableViewCell : StandardTableViewCell {
10+ final class IssueTableViewCell : NSTableCellView {
11+ private var label : NSTextField !
12+ private var icon : NSImageView !
13+ private var secondaryLabel : NSTextField ?
14+ private var node : ( any IssueNode )
1115
12- private var nodeIconView : NSImageView ?
16+ let iconWidth : CGFloat = 22
1317
14- var issueNode : ( any IssueNode ) ?
18+ init ( frame: CGRect , node: ( any IssueNode ) ) {
19+ self . node = node
20+ super. init ( frame: frame)
1521
16- /// Initializes the `IssueTableViewCell` with the issue node item
17- /// - Parameters:
18- /// - frameRect: The frame of the cell.
19- /// - node: The issue node the cell represents.
20- /// - isEditable: Set to true if the user should be able to edit the name (rarely used for issues).
21- init ( frame frameRect: NSRect , node: ( any IssueNode ) ? , isEditable: Bool = false ) {
22- super. init ( frame: frameRect, isEditable: isEditable)
23- self . issueNode = node
22+ // Set up icon
23+ icon = NSImageView ( frame: . zero)
24+ icon. translatesAutoresizingMaskIntoConstraints = false
25+ icon. symbolConfiguration = . init( pointSize: 13 , weight: . regular, scale: . medium)
2426
25- configureForNode ( node)
27+ // Set the icon color based on the type of issue node
28+ if let projectIssueNode = node as? ProjectIssueNode {
29+ icon? . image = projectIssueNode. nsIcon
30+ icon? . contentTintColor = NSColor . folderBlue
31+
32+ let issuesCount = projectIssueNode. errorCount + projectIssueNode. warningCount
33+ let pluralizationKey = issuesCount == 1 ? " issue " : " issues "
34+ createSecondaryLabel ( value: " \( issuesCount) \( pluralizationKey) " )
35+ } else if let fileIssueNode = node as? FileIssueNode {
36+ icon? . image = fileIssueNode. nsIcon
37+ if Settings . shared. preferences. general. fileIconStyle == . color {
38+ icon? . contentTintColor = NSColor ( fileIssueNode. iconColor)
39+ } else {
40+ icon? . contentTintColor = NSColor . coolGray
41+ }
42+ } else if let diagnosticNode = node as? DiagnosticIssueNode {
43+ icon? . image = diagnosticNode. nsIcon
44+ . withSymbolConfiguration (
45+ NSImage . SymbolConfiguration ( paletteColors: [ . white, diagnosticNode. severityColor] )
46+ )
47+ icon? . contentTintColor = diagnosticNode. severityColor
48+ }
49+
50+ self . addSubview ( icon)
51+ self . imageView = icon
52+
53+ createLabel ( )
54+ setConstraints ( )
2655 }
2756
28- override func configLabel( label: NSTextField , isEditable: Bool ) {
29- super. configLabel ( label: label, isEditable: isEditable)
57+ func createLabel( ) {
58+ if let diagnosticNode = node as? DiagnosticIssueNode {
59+ label = NSTextField ( wrappingLabelWithString: diagnosticNode. name)
60+ } else {
61+ label = NSTextField ( labelWithString: node. name)
62+ }
3063
31- if issueNode is DiagnosticIssueNode {
32- label. maximumNumberOfLines = 4
33- label. lineBreakMode = . byTruncatingTail
64+ label. translatesAutoresizingMaskIntoConstraints = false
65+ label. drawsBackground = false
66+ label. isBordered = false
67+ label. isEditable = false
68+ label. isSelectable = false
69+ label. layer? . cornerRadius = 10.0
70+ label. font = . labelFont( ofSize: fontSize)
71+
72+ if node is DiagnosticIssueNode {
73+ label. maximumNumberOfLines = Settings . shared. preferences. general. issueNavigatorDetail. rawValue
74+ label. allowsDefaultTighteningForTruncation = false
75+ label. cell? . truncatesLastVisibleLine = true
3476 label. cell? . wraps = true
35- label. cell? . isScrollable = false
36- label. preferredMaxLayoutWidth = frame. width - iconWidth - 20
77+ label. preferredMaxLayoutWidth = frame. width
3778 } else {
3879 label. lineBreakMode = . byTruncatingTail
3980 }
40- }
4181
42- override func configSecondaryLabel( secondaryLabel: NSTextField ) {
43- super. configSecondaryLabel ( secondaryLabel: secondaryLabel)
44- secondaryLabel. font = . systemFont( ofSize: fontSize- 2 , weight: . medium)
82+ self . addSubview ( label)
83+ self . textField = label
4584 }
4685
47- func configureForNode( _ node: ( any IssueNode ) ? ) {
48- guard let node = node else { return }
49-
50- secondaryLabelRightAligned = true
51- textField? . stringValue = node. name
86+ func createSecondaryLabel( value: String ) {
87+ let secondaryLabel = NSTextField ( frame: . zero)
88+ secondaryLabel. translatesAutoresizingMaskIntoConstraints = false
89+ secondaryLabel. drawsBackground = false
90+ secondaryLabel. isBordered = false
91+ secondaryLabel. isEditable = false
92+ secondaryLabel. isSelectable = false
93+ secondaryLabel. layer? . cornerRadius = 10.0
94+ secondaryLabel. font = . systemFont( ofSize: fontSize)
95+ secondaryLabel. alignment = . center
96+ secondaryLabel. textColor = . secondaryLabelColor
97+ secondaryLabel. stringValue = value
98+
99+ self . addSubview ( secondaryLabel)
100+ self . secondaryLabel = secondaryLabel
101+ }
52102
53- if let projectIssueNode = node as? ProjectIssueNode {
54- imageView? . image = projectIssueNode. nsIcon
55- imageView? . contentTintColor = NSColor . folderBlue
56- } else if let fileIssueNode = node as? FileIssueNode {
57- imageView? . image = fileIssueNode. nsIcon
58- if Settings . shared. preferences. general. fileIconStyle == . color {
59- imageView? . contentTintColor = NSColor ( fileIssueNode. iconColor)
60- } else {
61- imageView? . contentTintColor = NSColor . coolGray
62- }
63- } else if let diagnosticNode = node as? DiagnosticIssueNode {
64- imageView? . image = diagnosticNode. nsIcon
65- . withSymbolConfiguration (
66- NSImage . SymbolConfiguration ( paletteColors: [ . white, diagnosticNode. severityColor] )
67- )
68- imageView? . contentTintColor = diagnosticNode. severityColor
103+ func setConstraints( ) {
104+ if node is DiagnosticIssueNode {
105+ // For diagnostic nodes, place icon at the top
106+ NSLayoutConstraint . activate ( [
107+ icon. leadingAnchor. constraint ( equalTo: leadingAnchor, constant: 2 ) ,
108+ icon. topAnchor. constraint ( equalTo: topAnchor, constant: 4 ) ,
109+ icon. widthAnchor. constraint ( equalToConstant: 16 ) ,
110+ icon. heightAnchor. constraint ( equalToConstant: 16 ) ,
111+
112+ label. leadingAnchor. constraint ( equalTo: icon. trailingAnchor, constant: 6 ) ,
113+ label. trailingAnchor. constraint ( equalTo: trailingAnchor, constant: - 2 ) ,
114+ label. topAnchor. constraint ( equalTo: topAnchor, constant: 4 ) ,
115+ label. bottomAnchor. constraint ( equalTo: bottomAnchor, constant: - 4 )
116+ ] )
117+ } else if let secondaryLabel = secondaryLabel {
118+ // Secondary label
119+ NSLayoutConstraint . activate ( [
120+ icon. leadingAnchor. constraint ( equalTo: leadingAnchor, constant: 2 ) ,
121+ icon. centerYAnchor. constraint ( equalTo: centerYAnchor) ,
122+ icon. widthAnchor. constraint ( equalToConstant: 16 ) ,
123+ icon. heightAnchor. constraint ( equalToConstant: 16 ) ,
124+
125+ label. leadingAnchor. constraint ( equalTo: icon. trailingAnchor, constant: 6 ) ,
126+ label. centerYAnchor. constraint ( equalTo: centerYAnchor) ,
127+
128+ secondaryLabel. leadingAnchor. constraint ( equalTo: label. trailingAnchor, constant: 4 ) ,
129+ secondaryLabel. centerYAnchor. constraint ( equalTo: centerYAnchor) ,
130+ secondaryLabel. trailingAnchor. constraint ( lessThanOrEqualTo: trailingAnchor, constant: - 8 )
131+ ] )
132+ } else {
133+ // All other nodes
134+ NSLayoutConstraint . activate ( [
135+ icon. leadingAnchor. constraint ( equalTo: leadingAnchor, constant: 2 ) ,
136+ icon. centerYAnchor. constraint ( equalTo: centerYAnchor) ,
137+ icon. widthAnchor. constraint ( equalToConstant: 16 ) ,
138+ icon. heightAnchor. constraint ( equalToConstant: 16 ) ,
139+
140+ label. leadingAnchor. constraint ( equalTo: icon. trailingAnchor, constant: 4 ) ,
141+ label. trailingAnchor. constraint ( equalTo: trailingAnchor, constant: - 8 ) ,
142+ label. centerYAnchor. constraint ( equalTo: centerYAnchor)
143+ ] )
69144 }
145+ }
70146
71- if let projectNode = node as? ProjectIssueNode {
72- let issuesCount = projectNode . errorCount + projectNode . warningCount
147+ override func layout ( ) {
148+ super . layout ( )
73149
74- if issuesCount > 0 {
75- secondaryLabelRightAligned = false
76- secondaryLabel? . stringValue = " \( issuesCount) issues "
77- }
150+ if node is DiagnosticIssueNode {
151+ let availableWidth = frame. width
152+ label. preferredMaxLayoutWidth = availableWidth
78153 }
79154 }
80155
156+ required init ? ( coder: NSCoder ) {
157+ fatalError ( " init(coder:) has not been implemented " )
158+ }
159+
81160 /// Returns the font size for the current row height. Defaults to `13.0`
82161 private var fontSize : Double {
83162 switch self . frame. height {
@@ -87,12 +166,4 @@ class IssueTableViewCell: StandardTableViewCell {
87166 default : return 13
88167 }
89168 }
90-
91- override init ( frame frameRect: NSRect ) {
92- super. init ( frame: frameRect)
93- }
94-
95- required init ? ( coder: NSCoder ) {
96- fatalError ( " init?(coder: NSCoder) isn't implemented on `IssueTableViewCell`. " )
97- }
98169}
0 commit comments