1
1
mirror of https://github.com/danbee/persephone synced 2025-03-04 08:39:11 +00:00

Draw separator lines on the song list table

This commit is contained in:
Daniel Barber 2019-06-02 22:07:37 -04:00
parent 31b764905a
commit 2bac18187c
Signed by: danbarber
GPG Key ID: 931D8112E0103DD8
9 changed files with 192 additions and 45 deletions

View File

@ -56,6 +56,7 @@
E450AD9522262DF10091BED3 /* CoverArtQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = E450AD9422262DF10091BED3 /* CoverArtQueue.swift */; };
E450AD98222633920091BED3 /* Alamofire.framework.dSYM in Resources */ = {isa = PBXBuildFile; fileRef = E450AD96222633920091BED3 /* Alamofire.framework.dSYM */; };
E450ADA12229E7C90091BED3 /* PMKFoundation.framework.dSYM in Resources */ = {isa = PBXBuildFile; fileRef = E450AD9F2229E7C90091BED3 /* PMKFoundation.framework.dSYM */; };
E45878382296173C00586A1C /* AlbumDetailSongRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E45878372296173C00586A1C /* AlbumDetailSongRowView.swift */; };
E45962C62241A78500FC1A1E /* MPDCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = E45962C52241A78500FC1A1E /* MPDCommand.swift */; };
E45E4FDA22515D87004B537F /* CHANGELOG.md in Resources */ = {isa = PBXBuildFile; fileRef = E45E4FD722515D87004B537F /* CHANGELOG.md */; };
E45E4FDB22515D87004B537F /* Brewfile in Resources */ = {isa = PBXBuildFile; fileRef = E45E4FD822515D87004B537F /* Brewfile */; };
@ -70,6 +71,7 @@
E47E2FDD2220A6D100F747E6 /* Time.swift in Sources */ = {isa = PBXBuildFile; fileRef = E47E2FDC2220A6D100F747E6 /* Time.swift */; };
E47E2FE52220AA0700F747E6 /* AlbumViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = E47E2FE42220AA0700F747E6 /* AlbumViewLayout.swift */; };
E4928E0B2218D62A001D4BEA /* CGColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4928E0A2218D62A001D4BEA /* CGColor.swift */; };
E4A3A6A122A457B600EA2C40 /* AlbumDetailSongListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4A3A6A022A457B600EA2C40 /* AlbumDetailSongListView.swift */; };
E4A642DA22090CBE00067D21 /* MPDStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4A642D922090CBE00067D21 /* MPDStatus.swift */; };
E4A83BEF2221F8CF0098FED6 /* CoverArtPrefsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4A83BEE2221F8CF0098FED6 /* CoverArtPrefsController.swift */; };
E4A83BF12221FAA00098FED6 /* PreferencesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4A83BF02221FAA00098FED6 /* PreferencesViewController.swift */; };
@ -270,6 +272,7 @@
E450AD9E2229B9BC0091BED3 /* PersephoneBridgingHeader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PersephoneBridgingHeader.h; sourceTree = "<group>"; };
E450AD9F2229E7C90091BED3 /* PMKFoundation.framework.dSYM */ = {isa = PBXFileReference; lastKnownFileType = wrapper.dsym; name = PMKFoundation.framework.dSYM; path = Carthage/Build/Mac/PMKFoundation.framework.dSYM; sourceTree = "<group>"; };
E450ADA02229E7C90091BED3 /* PMKFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PMKFoundation.framework; path = Carthage/Build/Mac/PMKFoundation.framework; sourceTree = "<group>"; };
E45878372296173C00586A1C /* AlbumDetailSongRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlbumDetailSongRowView.swift; sourceTree = "<group>"; };
E45962C52241A78500FC1A1E /* MPDCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPDCommand.swift; sourceTree = "<group>"; };
E45E4FD722515D87004B537F /* CHANGELOG.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = CHANGELOG.md; sourceTree = SOURCE_ROOT; };
E45E4FD822515D87004B537F /* Brewfile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Brewfile; sourceTree = SOURCE_ROOT; };
@ -285,6 +288,7 @@
E47E2FDC2220A6D100F747E6 /* Time.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Time.swift; sourceTree = "<group>"; };
E47E2FE42220AA0700F747E6 /* AlbumViewLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlbumViewLayout.swift; sourceTree = "<group>"; };
E4928E0A2218D62A001D4BEA /* CGColor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CGColor.swift; sourceTree = "<group>"; };
E4A3A6A022A457B600EA2C40 /* AlbumDetailSongListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlbumDetailSongListView.swift; sourceTree = "<group>"; };
E4A642D922090CBE00067D21 /* MPDStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPDStatus.swift; sourceTree = "<group>"; };
E4A83BEE2221F8CF0098FED6 /* CoverArtPrefsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoverArtPrefsController.swift; sourceTree = "<group>"; };
E4A83BF02221FAA00098FED6 /* PreferencesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesViewController.swift; sourceTree = "<group>"; };
@ -464,6 +468,8 @@
E47E2FD222205D2500F747E6 /* MainWindow.swift */,
E4B11BB7227538FA0075461B /* CurrentCoverArtView.swift */,
E423563F228623D2001216D6 /* QueueSongTitleView.swift */,
E45878372296173C00586A1C /* AlbumDetailSongRowView.swift */,
E4A3A6A022A457B600EA2C40 /* AlbumDetailSongListView.swift */,
);
path = Views;
sourceTree = "<group>";
@ -970,10 +976,12 @@
E41E530E223EF4CF00173814 /* CoverArtService+Caching.swift in Sources */,
E4E8CC922204F4B80024217A /* QueueViewController.swift in Sources */,
E440519C227BAF2E0090CD6F /* UIActions.swift in Sources */,
E45878382296173C00586A1C /* AlbumDetailSongRowView.swift in Sources */,
E41E5312223EF74A00173814 /* CoverArtService+Filesystem.swift in Sources */,
E41E5301223BF99300173814 /* MPDClient+Queue.swift in Sources */,
E4EB237B220F7CF1008C70C0 /* MPDAlbum.swift in Sources */,
E41E5303223BF9C300173814 /* MPDClient+Idle.swift in Sources */,
E4A3A6A122A457B600EA2C40 /* AlbumDetailSongListView.swift in Sources */,
E4B11B53226928F20075461B /* AppState.swift in Sources */,
E435E3E4221CD75D00184CFC /* NSImage.swift in Sources */,
E440519A22787CF60090CD6F /* MPDReducer.swift in Sources */,

View File

@ -22,8 +22,8 @@ class AlbumDetailView: NSViewController {
albumTracksView.dataSource = dataSource
albumTracksView.delegate = self
albumTracksView.intercellSpacing = CGSize(width: 0, height: 13)
albumTracksView.gridStyleMask = .solidHorizontalGridLineMask
albumTracksView.intercellSpacing = CGSize(width: 0, height: 18)
albumTracksView.floatsGroupRows = false
albumCoverView.wantsLayer = true
albumCoverView.layer?.cornerRadius = 5
@ -47,9 +47,11 @@ class AlbumDetailView: NSViewController {
func getAlbumSongs(for album: Album) {
App.mpdClient.getAlbumSongs(for: album.mpdAlbum) { (mpdSongs: [MPDClient.MPDSong]) in
self.dataSource.albumTracks = mpdSongs.map {
return Song(mpdSong: $0)
}
self.dataSource.setAlbumSongs(
mpdSongs.map { Song(mpdSong: $0) }
)
self.getBigCoverArt(song: self.dataSource.albumSongs.first!.song ?? self.dataSource.albumSongs[1].song!)
DispatchQueue.main.async {
self.albumTracksView.reloadData()
@ -57,6 +59,20 @@ class AlbumDetailView: NSViewController {
}
}
func getBigCoverArt(song: Song) {
let coverArtService = CoverArtService(song: song)
coverArtService.fetchBigCoverArt()
.done() { image in
DispatchQueue.main.async {
if let image = image {
self.albumCoverView.image = image
}
}
}
.cauterize()
}
func setAppearance() {
if #available(OSX 10.14, *) {
let darkMode = NSApp.effectiveAppearance.bestMatch(from:
@ -75,26 +91,45 @@ class AlbumDetailView: NSViewController {
extension AlbumDetailView: NSTableViewDelegate {
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
let song = dataSource.albumTracks[row]
switch tableColumn?.identifier.rawValue {
case "trackNumberColumn":
return cellForTrackNumber(tableView, with: song)
case "trackTitleColumn":
return cellForSongTitle(tableView, with: song)
case "trackDurationColumn":
return cellForSongDuration(tableView, with: song)
default:
return nil
if let song = dataSource.albumSongs[row].song {
switch tableColumn?.identifier.rawValue {
case "trackNumberColumn":
return cellForTrackNumber(tableView, with: song)
case "trackTitleColumn":
return cellForSongTitle(tableView, with: song)
case "trackDurationColumn":
return cellForSongDuration(tableView, with: song)
default:
return nil
}
} else if let disc = dataSource.albumSongs[row].disc {
return cellForDiscNumber(tableView, with: disc)
}
return nil
}
func tableView(_ tableView: NSTableView, isGroupRow row: Int) -> Bool {
return dataSource.albumSongs[row].disc != nil
}
func tableView(_ tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? {
let view = NSTableRowView()
let view = AlbumDetailSongRowView()
return view
}
func cellForDiscNumber(_ tableView: NSTableView, with disc: String) -> NSView {
let cellView = tableView.makeView(
withIdentifier: .discNumber,
owner: self
) as! NSTableCellView
cellView.textField?.stringValue = "Disc \(disc)"
return cellView
}
func cellForTrackNumber(_ tableView: NSTableView, with song: Song) -> NSView {
let cellView = tableView.makeView(
withIdentifier: .trackNumber,

View File

@ -9,9 +9,37 @@
import AppKit
class AlbumTracksDataSource: NSObject, NSTableViewDataSource {
var albumTracks: [Song] = []
struct AlbumSongItem {
let disc: String?
let song: Song?
init(song: Song) {
self.disc = nil
self.song = song
}
init(disc: String) {
self.disc = disc
self.song = nil
}
}
var albumSongs: [AlbumSongItem] = []
func setAlbumSongs(_ songs: [Song]) {
var disc: String? = ""
songs.forEach { song in
if song.disc != disc {
disc = song.disc
albumSongs.append(AlbumSongItem(disc: song.disc))
}
albumSongs.append(AlbumSongItem(song: song))
}
}
func numberOfRows(in tableView: NSTableView) -> Int {
return albumTracks.count
return albumSongs.count
}
}

View File

@ -18,6 +18,7 @@ extension NSUserInterfaceItemIdentifier {
static let albumViewItem = NSUserInterfaceItemIdentifier("AlbumViewItem")
static let discNumber = NSUserInterfaceItemIdentifier("discNumberCell")
static let trackNumber = NSUserInterfaceItemIdentifier("trackNumberCell")
static let songTitle = NSUserInterfaceItemIdentifier("songTitleCell")
static let songDuration = NSUserInterfaceItemIdentifier("songDurationCell")

View File

@ -11,6 +11,10 @@ import Foundation
struct Song {
var mpdSong: MPDClient.MPDSong
var disc: String {
return mpdSong.getTag(.disc)
}
var trackNumber: String {
return mpdSong.getTag(.track)
}

View File

@ -22,9 +22,9 @@
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="m2v-pR-e9v">
<rect key="frame" x="357" y="512" width="448" height="29"/>
<rect key="frame" x="357" y="507" width="448" height="29"/>
<constraints>
<constraint firstAttribute="width" constant="444" id="64T-pe-ww2"/>
<constraint firstAttribute="width" constant="444" id="erC-QS-9hc"/>
</constraints>
<textFieldCell key="cell" title="Album Title" id="URb-mh-vZz">
<font key="font" metaFont="systemSemibold" size="24"/>
@ -33,7 +33,7 @@
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="4Jx-I5-Nkv">
<rect key="frame" x="357" y="485" width="448" height="19"/>
<rect key="frame" x="357" y="480" width="448" height="19"/>
<textFieldCell key="cell" title="Artist Name" id="ztJ-4E-qvI">
<font key="font" metaFont="system" size="16"/>
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
@ -41,29 +41,33 @@
</textFieldCell>
</textField>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="FWd-vZ-5CT">
<rect key="frame" x="31" y="241" width="300" height="300"/>
<rect key="frame" x="31" y="236" width="300" height="300"/>
<constraints>
<constraint firstAttribute="height" constant="300" id="WkH-QY-IM1"/>
<constraint firstAttribute="width" secondItem="FWd-vZ-5CT" secondAttribute="height" multiplier="1:1" id="m2r-ee-czT"/>
<constraint firstAttribute="height" constant="300" id="69o-NQ-qL7"/>
<constraint firstAttribute="width" constant="300" id="8XY-bQ-C7X"/>
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="300" id="cyo-wr-hV8"/>
</constraints>
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyUpOrDown" image="defaultCoverArt" id="scE-kj-gex"/>
</imageView>
<button verticalHuggingPriority="750" fixedFrame="YES" imageHugsTitle="YES" translatesAutoresizingMaskIntoConstraints="NO" id="jMU-bv-TNF">
<rect key="frame" x="31" y="182" width="119" height="35"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<button verticalHuggingPriority="750" imageHugsTitle="YES" translatesAutoresizingMaskIntoConstraints="NO" id="jMU-bv-TNF">
<rect key="frame" x="31" y="177" width="119" height="35"/>
<constraints>
<constraint firstAttribute="height" constant="33" id="2uQ-mC-4QY"/>
<constraint firstAttribute="width" constant="119" id="h2n-ZB-Ufr"/>
</constraints>
<buttonCell key="cell" type="smallSquare" title="Play Album" bezelStyle="smallSquare" image="playButton" imagePosition="left" alignment="center" lineBreakMode="truncatingTail" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Rtg-Zd-JYc">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
</button>
<scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="19" horizontalPageScroll="10" verticalLineScroll="19" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="BOb-Lr-10M">
<rect key="frame" x="359" y="30" width="444" height="426"/>
<rect key="frame" x="359" y="33" width="444" height="418"/>
<clipView key="contentView" drawsBackground="NO" copiesOnScroll="NO" id="9QN-UB-b4l">
<rect key="frame" x="0.0" y="0.0" width="444" height="426"/>
<rect key="frame" x="0.0" y="0.0" width="444" height="418"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="none" columnSelection="YES" multipleSelection="NO" autosaveColumns="NO" rowSizeStyle="automatic" viewBased="YES" id="ehr-qh-87Q">
<rect key="frame" x="0.0" y="0.0" width="444" height="426"/>
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="none" columnSelection="YES" multipleSelection="NO" autosaveColumns="NO" rowSizeStyle="automatic" viewBased="YES" id="ehr-qh-87Q" customClass="AlbumDetailSongListView" customModule="Persephone" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="444" height="418"/>
<autoresizingMask key="autoresizingMask"/>
<size key="intercellSpacing" width="3" height="2"/>
<color key="backgroundColor" red="0.11764705882352941" green="0.11764705882352941" blue="0.11764705882352941" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
@ -104,6 +108,30 @@
<outlet property="textField" destination="6eU-Jx-HDR" id="DWy-vj-9Eq"/>
</connections>
</tableCellView>
<tableCellView identifier="discNumberCell" id="MHh-8c-iyL">
<rect key="frame" x="1" y="20" width="40" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="nwx-zY-r5o">
<rect key="frame" x="0.0" y="0.0" width="441" height="17"/>
<constraints>
<constraint firstAttribute="width" constant="437" id="irN-AG-Pcj"/>
</constraints>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Disc 1" id="jya-2a-lit">
<font key="font" metaFont="systemBold"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<constraints>
<constraint firstItem="nwx-zY-r5o" firstAttribute="centerY" secondItem="MHh-8c-iyL" secondAttribute="centerY" id="IOV-5t-KTN"/>
<constraint firstItem="nwx-zY-r5o" firstAttribute="leading" secondItem="MHh-8c-iyL" secondAttribute="leading" constant="2" id="nw0-ya-Pwt"/>
</constraints>
<connections>
<outlet property="textField" destination="nwx-zY-r5o" id="NFl-7o-wmK"/>
</connections>
</tableCellView>
</prototypeCellViews>
</tableColumn>
<tableColumn identifier="trackTitleColumn" width="353" minWidth="40" maxWidth="1000" id="7yp-QQ-EzC">
@ -196,17 +224,20 @@
</scrollView>
</subviews>
<constraints>
<constraint firstAttribute="bottom" secondItem="BOb-Lr-10M" secondAttribute="bottom" constant="30" id="AaR-Nq-vZD"/>
<constraint firstItem="4Jx-I5-Nkv" firstAttribute="top" secondItem="m2v-pR-e9v" secondAttribute="bottom" constant="8" symbolic="YES" id="P10-cj-Iaz"/>
<constraint firstItem="m2v-pR-e9v" firstAttribute="leading" secondItem="4Jx-I5-Nkv" secondAttribute="leading" id="PVJ-Rk-9K5"/>
<constraint firstItem="m2v-pR-e9v" firstAttribute="trailing" secondItem="4Jx-I5-Nkv" secondAttribute="trailing" id="PlO-jD-clF"/>
<constraint firstItem="FWd-vZ-5CT" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" constant="31" id="Pyj-e4-N8r"/>
<constraint firstItem="FWd-vZ-5CT" firstAttribute="top" secondItem="Hz6-mo-xeY" secondAttribute="top" constant="20" symbolic="YES" id="Yvv-MA-LPf"/>
<constraint firstItem="m2v-pR-e9v" firstAttribute="leading" secondItem="BOb-Lr-10M" secondAttribute="leading" id="aLT-36-8oT"/>
<constraint firstItem="m2v-pR-e9v" firstAttribute="trailing" secondItem="BOb-Lr-10M" secondAttribute="trailing" id="dpm-La-xDl"/>
<constraint firstItem="BOb-Lr-10M" firstAttribute="top" secondItem="4Jx-I5-Nkv" secondAttribute="bottom" constant="29" id="f3Q-VP-2Y2"/>
<constraint firstAttribute="trailing" secondItem="m2v-pR-e9v" secondAttribute="trailing" constant="20" symbolic="YES" id="sEh-fo-Kqa"/>
<constraint firstItem="m2v-pR-e9v" firstAttribute="top" secondItem="FWd-vZ-5CT" secondAttribute="top" id="zLA-y0-JQ9"/>
<constraint firstItem="FWd-vZ-5CT" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" constant="31" id="694-aS-G4N"/>
<constraint firstItem="jMU-bv-TNF" firstAttribute="leading" secondItem="FWd-vZ-5CT" secondAttribute="leading" id="AwZ-M4-fep"/>
<constraint firstItem="BOb-Lr-10M" firstAttribute="leading" secondItem="4Jx-I5-Nkv" secondAttribute="leading" id="GEK-R3-Sw6"/>
<constraint firstItem="BOb-Lr-10M" firstAttribute="top" secondItem="4Jx-I5-Nkv" secondAttribute="bottom" constant="29" id="K5g-Kd-iHK"/>
<constraint firstAttribute="bottom" secondItem="BOb-Lr-10M" secondAttribute="bottom" constant="33" id="MZ6-81-2qe"/>
<constraint firstItem="4Jx-I5-Nkv" firstAttribute="leading" secondItem="m2v-pR-e9v" secondAttribute="leading" id="NaJ-VT-uln"/>
<constraint firstItem="FWd-vZ-5CT" firstAttribute="top" secondItem="Hz6-mo-xeY" secondAttribute="top" constant="25" id="QA9-xn-fzY"/>
<constraint firstItem="m2v-pR-e9v" firstAttribute="top" secondItem="FWd-vZ-5CT" secondAttribute="top" id="bqi-HD-KZW"/>
<constraint firstItem="jMU-bv-TNF" firstAttribute="top" secondItem="FWd-vZ-5CT" secondAttribute="bottom" constant="25" id="dd1-6b-TEN"/>
<constraint firstItem="4Jx-I5-Nkv" firstAttribute="trailing" secondItem="m2v-pR-e9v" secondAttribute="trailing" id="dmh-TC-Ncr"/>
<constraint firstItem="m2v-pR-e9v" firstAttribute="leading" secondItem="FWd-vZ-5CT" secondAttribute="trailing" constant="28" id="icS-vq-PkK"/>
<constraint firstItem="4Jx-I5-Nkv" firstAttribute="top" secondItem="m2v-pR-e9v" secondAttribute="bottom" constant="8" symbolic="YES" id="nTZ-Ew-sDQ"/>
<constraint firstAttribute="trailing" secondItem="m2v-pR-e9v" secondAttribute="trailing" constant="20" symbolic="YES" id="qyi-X9-6B9"/>
<constraint firstItem="BOb-Lr-10M" firstAttribute="trailing" secondItem="4Jx-I5-Nkv" secondAttribute="trailing" id="sPx-cY-MeX"/>
</constraints>
<point key="canvasLocation" x="262.5" y="117.5"/>
</customView>

View File

@ -569,8 +569,8 @@
<rect key="frame" x="1" y="1" width="200" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="xgd-Cz-np3">
<rect key="frame" x="0.0" y="2" width="447" height="14"/>
<textField verticalHuggingPriority="750" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="xgd-Cz-np3">
<rect key="frame" x="0.0" y="2" width="322" height="14"/>
<constraints>
<constraint firstAttribute="width" constant="443" id="mkA-ng-q8a"/>
</constraints>

View File

@ -0,0 +1,13 @@
//
// AlbumDetailSongListView.swift
// Persephone
//
// Created by Daniel Barber on 2019/6/02.
// Copyright © 2019 Dan Barber. All rights reserved.
//
import AppKit
class AlbumDetailSongListView: NSTableView {
override func drawGrid(inClipRect clipRect: NSRect) { }
}

View File

@ -0,0 +1,27 @@
//
// AlbumDetailSongRowView.swift
// Persephone
//
// Created by Daniel Barber on 2019/5/22.
// Copyright © 2019 Dan Barber. All rights reserved.
//
import AppKit
class AlbumDetailSongRowView: NSTableRowView {
override func drawBackground(in dirtyRect: NSRect) {
let borderPath = CGMutablePath()
let startingPoint = CGPoint(x: dirtyRect.origin.x, y: dirtyRect.height)
let endingPoint = CGPoint(x: dirtyRect.width, y: dirtyRect.height)
borderPath.move(to: startingPoint)
borderPath.addLine(to: endingPoint)
let shapeLayer = CAShapeLayer()
self.layer?.addSublayer(shapeLayer)
shapeLayer.path = borderPath
shapeLayer.strokeColor = NSColor.secondaryLabelColor.cgColor
shapeLayer.lineWidth = 1
}
}