diff --git a/Aural.xcodeproj/project.xcworkspace/xcuserdata/kven.xcuserdatad/UserInterfaceState.xcuserstate b/Aural.xcodeproj/project.xcworkspace/xcuserdata/kven.xcuserdatad/UserInterfaceState.xcuserstate index ec1ffd7ea..b2aa1f593 100644 Binary files a/Aural.xcodeproj/project.xcworkspace/xcuserdata/kven.xcuserdatad/UserInterfaceState.xcuserstate and b/Aural.xcodeproj/project.xcworkspace/xcuserdata/kven.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/Source/Core/Utils/Extensions/StringExtensions.swift b/Source/Core/Utils/Extensions/StringExtensions.swift index 7ccc6a236..1d765ff51 100644 --- a/Source/Core/Utils/Extensions/StringExtensions.swift +++ b/Source/Core/Utils/Extensions/StringExtensions.swift @@ -460,6 +460,13 @@ extension NSMutableParagraphStyle { return style }() + static let byWordWrapping: NSMutableParagraphStyle = { + + let style: NSMutableParagraphStyle = NSMutableParagraphStyle() + style.lineBreakMode = .byWordWrapping + return style + }() + convenience init(lineSpacing: CGFloat) { self.init() diff --git a/Source/UI/CompactPlayer/CompactPlayerUIState.swift b/Source/UI/CompactPlayer/CompactPlayerUIState.swift index bba088c30..6b9f3f6b6 100644 --- a/Source/UI/CompactPlayer/CompactPlayerUIState.swift +++ b/Source/UI/CompactPlayer/CompactPlayerUIState.swift @@ -46,4 +46,5 @@ enum CompactPlayerDisplayedView { case search case effects case trackInfo + case lyrics } diff --git a/Source/UI/CompactPlayer/CompactPlayerWindowController.swift b/Source/UI/CompactPlayer/CompactPlayerWindowController.swift index 869390027..69199e266 100644 --- a/Source/UI/CompactPlayer/CompactPlayerWindowController.swift +++ b/Source/UI/CompactPlayer/CompactPlayerWindowController.swift @@ -34,6 +34,7 @@ class CompactPlayerWindowController: NSWindowController { let searchViewController: CompactPlayQueueSearchViewController = .init() let chaptersListViewController: CompactChaptersListViewController = .init() let trackInfoViewController: CompactPlayerTrackInfoViewController = .init() + let lyricsViewController: CompactPlayerLyricsViewController = .init() lazy var effectsViewLoader: LazyViewLoader = .init() private var effectsSheetViewController: EffectsSheetViewController {effectsViewLoader.controller} @@ -56,6 +57,7 @@ class CompactPlayerWindowController: NSWindowController { tabView.tabViewItem(at: 2).view?.addSubview(searchViewController.view) tabView.tabViewItem(at: 3).view?.addSubview(chaptersListViewController.view) tabView.tabViewItem(at: 4).view?.addSubview(trackInfoViewController.view) + tabView.tabViewItem(at: 5).view?.addSubview(lyricsViewController.view) playQueueViewController.view.anchorToSuperview() searchViewController.view.anchorToSuperview() @@ -81,6 +83,8 @@ class CompactPlayerWindowController: NSWindowController { messenger.subscribe(to: .View.toggleTrackInfo, handler: showTrackInfo) messenger.subscribe(to: .Player.trackInfo, handler: showTrackInfo) + messenger.subscribe(to: .View.toggleLyrics, handler: showLyrics) + // messenger.subscribe(to: .View.toggleVisualizer, handler: toggleVisualizer) messenger.subscribe(to: .View.changeWindowCornerRadius, handler: changeWindowCornerRadius(to:)) @@ -200,6 +204,10 @@ class CompactPlayerWindowController: NSWindowController { tabView.selectTabViewItem(at: 4) } + private func showLyrics() { + tabView.selectTabViewItem(at: 5) + } + func showPlayingTrackInPlayQueue() { showPlayQueue() } @@ -248,6 +256,9 @@ class CompactPlayerWindowController: NSWindowController { case 4: compactPlayerUIState.displayedView = .trackInfo + case 5: + compactPlayerUIState.displayedView = .lyrics + default: return } diff --git a/Source/UI/CompactPlayer/Lyrics/CompactPlayerLyrics.xib b/Source/UI/CompactPlayer/Lyrics/CompactPlayerLyrics.xib index 214d18199..d3bf284c2 100644 --- a/Source/UI/CompactPlayer/Lyrics/CompactPlayerLyrics.xib +++ b/Source/UI/CompactPlayer/Lyrics/CompactPlayerLyrics.xib @@ -6,10 +6,21 @@ - + + + + + + + + + + + + - + @@ -28,37 +39,223 @@ - - + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + + + @@ -66,15 +263,27 @@ - - - - + + + + + + + + + + + + + + + + diff --git a/Source/UI/CompactPlayer/Lyrics/CompactPlayerLyricsViewController.swift b/Source/UI/CompactPlayer/Lyrics/CompactPlayerLyricsViewController.swift index 378377667..f1a452c85 100644 --- a/Source/UI/CompactPlayer/Lyrics/CompactPlayerLyricsViewController.swift +++ b/Source/UI/CompactPlayer/Lyrics/CompactPlayerLyricsViewController.swift @@ -12,5 +12,25 @@ import AppKit class CompactPlayerLyricsViewController: LyricsViewController { + @IBOutlet weak var prototypeTextField: NSTextField! + override var nibName: NSNib.Name? {"CompactPlayerLyrics"} + + private static var columnBounds = NSMakeRect(.zero, .zero, 270, .greatestFiniteMagnitude) + + // Adjust row height based on if the text wraps over to the next line + override func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat { + + guard let text = self.timedLyrics?.lines[row].content else {return 30} + + // Set the key and value within the virtual text fields (which are not displayed) + prototypeTextField.font = systemFontScheme.lyricsHighlightFont + prototypeTextField.stringValue = text + + // And then compute row height from their cell sizes + let rowHeight = prototypeTextField.cell!.cellSize(forBounds: Self.columnBounds).height + + // The desired row height is the maximum of the two heights, plus some padding + return max(30, rowHeight + 5) + } } diff --git a/Source/UI/FontSchemes/Domain/FontScheme.swift b/Source/UI/FontSchemes/Domain/FontScheme.swift index 157a1e8a7..1c29af8a4 100644 --- a/Source/UI/FontSchemes/Domain/FontScheme.swift +++ b/Source/UI/FontSchemes/Domain/FontScheme.swift @@ -38,7 +38,7 @@ class FontScheme: NSObject, UserManagedObject { var prominentFont: NSFont { didSet { - self.lyricsHighlightFont = NSFont(name: prominentFont.familyName!, size: prominentFont.pointSize * 1.2)! + self.lyricsHighlightFont = NSFont(name: prominentFont.familyName!, size: prominentFont.pointSize * 1.1)! } } @@ -57,7 +57,7 @@ class FontScheme: NSObject, UserManagedObject { self.captionFont = captionFont self.normalFont = normalFont self.prominentFont = prominentFont - self.lyricsHighlightFont = NSFont(name: prominentFont.familyName!, size: prominentFont.pointSize * 1.2)! + self.lyricsHighlightFont = NSFont(name: prominentFont.familyName!, size: prominentFont.pointSize * 1.1)! self.smallFont = smallFont self.extraSmallFont = extraSmallFont @@ -93,7 +93,7 @@ class FontScheme: NSObject, UserManagedObject { self.normalFont = normalFont self.prominentFont = prominentFont - self.lyricsHighlightFont = NSFont(name: prominentFont.familyName!, size: prominentFont.pointSize * 1.2)! + self.lyricsHighlightFont = NSFont(name: prominentFont.familyName!, size: prominentFont.pointSize * 1.1)! self.smallFont = smallFont self.extraSmallFont = extraSmallFont diff --git a/Source/UI/Lyrics/Lyrics.xib b/Source/UI/Lyrics/Lyrics.xib index f1f617c15..0d1cd1382 100644 --- a/Source/UI/Lyrics/Lyrics.xib +++ b/Source/UI/Lyrics/Lyrics.xib @@ -23,7 +23,7 @@ - + @@ -57,7 +57,7 @@ - + @@ -97,16 +97,16 @@ - + - + - + @@ -119,11 +119,11 @@ - + - - + + @@ -163,7 +163,7 @@ - + @@ -186,7 +186,7 @@ - + diff --git a/Source/UI/Lyrics/LyricsViewController+Timed.swift b/Source/UI/Lyrics/LyricsViewController+Timed.swift index 0445d5636..20377e601 100644 --- a/Source/UI/Lyrics/LyricsViewController+Timed.swift +++ b/Source/UI/Lyrics/LyricsViewController+Timed.swift @@ -187,7 +187,7 @@ extension LyricsViewController: NSTableViewDelegate { } cell.textField?.show() - cell.textField?.lineBreakMode = .byTruncatingTail +// cell.textField?.lineBreakMode = .byWordWrapping return cell } @@ -201,6 +201,7 @@ extension LyricsViewController: NSTableViewDelegate { cell.text = line.content cell.textFont = systemFontScheme.lyricsHighlightFont cell.textColor = systemColorScheme.primarySelectedTextColor + cell.textField?.lineBreakMode = .byWordWrapping return } @@ -216,11 +217,16 @@ extension LyricsViewController: NSTableViewDelegate { let subString = line.content.substring(range: preSegmentRange.intRange) let attrStr = subString.attributed(font: systemFontScheme.lyricsHighlightFont, color: systemColorScheme.primarySelectedTextColor) +// attrStr.addAttribute(.paragraphStyle, value: NSMutableParagraphStyle.byWordWrapping, range: NSMakeRange(0, attrStr.length)) mutStr = mutStr + attrStr } let subString = line.content.substring(range: segment.range.intRange) - mutStr = mutStr + subString.attributed(font: systemFontScheme.lyricsHighlightFont, color: systemColorScheme.activeControlColor) + + let attrStr = subString.attributed(font: systemFontScheme.lyricsHighlightFont, color: systemColorScheme.activeControlColor) +// attrStr.addAttribute(.paragraphStyle, value: NSMutableParagraphStyle.byWordWrapping, range: NSMakeRange(0, attrStr.length)) + + mutStr = mutStr + attrStr let segmentLen = segment.range.length let segmentEnd = segmentLoc + segmentLen @@ -232,9 +238,14 @@ extension LyricsViewController: NSTableViewDelegate { let subString = line.content.substring(range: postSegmentRange.intRange) let attrStr = subString.attributed(font: systemFontScheme.lyricsHighlightFont, color: systemColorScheme.primarySelectedTextColor) +// attrStr.addAttribute(.paragraphStyle, value: NSMutableParagraphStyle.byWordWrapping, range: NSMakeRange(0, attrStr.length)) + mutStr = mutStr + attrStr } + mutStr.addAttribute(.paragraphStyle, value: NSMutableParagraphStyle.byWordWrapping, range: NSMakeRange(0, mutStr.length)) + +// cell.textField?.lineBreakMode = .byWordWrapping cell.attributedText = mutStr } @@ -243,5 +254,6 @@ extension LyricsViewController: NSTableViewDelegate { cell.text = line.content cell.textFont = isCurrentLine ? systemFontScheme.lyricsHighlightFont : systemFontScheme.prominentFont cell.textColor = isCurrentLine ? systemColorScheme.activeControlColor : systemColorScheme.secondaryTextColor + cell.textField?.lineBreakMode = .byWordWrapping } } diff --git a/Source/UI/ModularPlayer/WindowManagement/WindowLayoutsManager.swift b/Source/UI/ModularPlayer/WindowManagement/WindowLayoutsManager.swift index dc0eb8199..5dc14050f 100644 --- a/Source/UI/ModularPlayer/WindowManagement/WindowLayoutsManager.swift +++ b/Source/UI/ModularPlayer/WindowManagement/WindowLayoutsManager.swift @@ -418,3 +418,15 @@ class WindowLayoutsManager: UserManagedObjects, Destroyable, Resto return WindowLayoutsPersistentState(systemLayout: systemLayoutState, userLayouts: userLayoutsState) } } + +extension NSRect: @retroactive Hashable { + + public func hash(into hasher: inout Hasher) { + + hasher.combine(minX) + hasher.combine(minY) + + hasher.combine(width) + hasher.combine(height) + } +} diff --git a/Source/UI/Utils/TableView/TableViewController/TableCellBuilder.swift b/Source/UI/Utils/TableView/TableViewController/TableCellBuilder.swift index d3e89a54e..d8371c2ef 100644 --- a/Source/UI/Utils/TableView/TableViewController/TableCellBuilder.swift +++ b/Source/UI/Utils/TableView/TableViewController/TableCellBuilder.swift @@ -83,12 +83,9 @@ class TableCellBuilder { selAttStr = selAttStr + strings[index].text.attributed(font: strings[index].font, color: selectedTextColors[index]) } } - - let style: NSMutableParagraphStyle = NSMutableParagraphStyle() - style.lineBreakMode = .byTruncatingTail - attStr.addAttribute(.paragraphStyle, value: style, range: NSMakeRange(0, attStr.length)) - selAttStr.addAttribute(.paragraphStyle, value: style, range: NSMakeRange(0, selAttStr.length)) + attStr.addAttribute(.paragraphStyle, value: NSMutableParagraphStyle.byTruncatingTail, range: NSMakeRange(0, attStr.length)) + selAttStr.addAttribute(.paragraphStyle, value: NSMutableParagraphStyle.byTruncatingTail, range: NSMakeRange(0, selAttStr.length)) self.attributedText = attStr self.selectedAttributedText = selAttStr