Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
47ca5186 by Claudio Cambra at 2025-11-24T05:51:16+00:00
macosx: Add VLCLibraryAudioDataSourceHeaderDelegate

Signed-off-by: Claudio Cambra <[email protected]>

- - - - -
ce3ffce9 by Claudio Cambra at 2025-11-24T05:51:16+00:00
macosx: Add new header delegate property to audio data source

Signed-off-by: Claudio Cambra <[email protected]>

- - - - -
c5f37759 by Claudio Cambra at 2025-11-24T05:51:16+00:00
macosx: Add a audio group table header view

Signed-off-by: Claudio Cambra <[email protected]>

- - - - -
7b418774 by Claudio Cambra at 2025-11-24T05:51:16+00:00
macosx: Configure audio group table header view and delegation for it in 
VLCLibraryAudioViewController

Signed-off-by: Claudio Cambra <[email protected]>

- - - - -
f04b622e by Claudio Cambra at 2025-11-24T05:51:16+00:00
macosx: Use an NSGlassEffectView for the audio group table header view on macOS 
26

Signed-off-by: Claudio Cambra <[email protected]>

- - - - -
05f437f9 by Claudio Cambra at 2025-11-24T05:51:16+00:00
macosx: Add VLCLibraryAudioGroupTableHeaderCell

Signed-off-by: Claudio Cambra <[email protected]>

- - - - -


10 changed files:

- modules/gui/macosx/Makefile.am
- modules/gui/macosx/library/audio-library/VLCLibraryAudioDataSource.h
- modules/gui/macosx/library/audio-library/VLCLibraryAudioDataSource.m
- + 
modules/gui/macosx/library/audio-library/VLCLibraryAudioDataSourceHeaderDelegate.h
- + 
modules/gui/macosx/library/audio-library/VLCLibraryAudioGroupTableHeaderCell.h
- + 
modules/gui/macosx/library/audio-library/VLCLibraryAudioGroupTableHeaderCell.m
- + 
modules/gui/macosx/library/audio-library/VLCLibraryAudioGroupTableHeaderView.h
- + 
modules/gui/macosx/library/audio-library/VLCLibraryAudioGroupTableHeaderView.m
- modules/gui/macosx/library/audio-library/VLCLibraryAudioViewController.h
- modules/gui/macosx/library/audio-library/VLCLibraryAudioViewController.m


Changes:

=====================================
modules/gui/macosx/Makefile.am
=====================================
@@ -276,11 +276,16 @@ libmacosx_plugin_la_SOURCES = \
        
gui/macosx/library/audio-library/VLCLibraryAllAudioGroupsMediaLibraryItem.h \
        
gui/macosx/library/audio-library/VLCLibraryAllAudioGroupsMediaLibraryItem.m \
        gui/macosx/library/audio-library/VLCLibraryAudioDataSource.h \
+       
gui/macosx/library/audio-library/VLCLibraryAudioDataSourceHeaderDelegate.h \
        gui/macosx/library/audio-library/VLCLibraryAudioDataSource.m \
        gui/macosx/library/audio-library/VLCLibraryAudioGroupDataSource.h \
        gui/macosx/library/audio-library/VLCLibraryAudioGroupDataSource.m \
        gui/macosx/library/audio-library/VLCLibraryAudioGroupHeaderView.h \
        gui/macosx/library/audio-library/VLCLibraryAudioGroupHeaderView.m \
+       gui/macosx/library/audio-library/VLCLibraryAudioGroupTableHeaderCell.h \
+       gui/macosx/library/audio-library/VLCLibraryAudioGroupTableHeaderCell.m \
+       gui/macosx/library/audio-library/VLCLibraryAudioGroupTableHeaderView.h \
+       gui/macosx/library/audio-library/VLCLibraryAudioGroupTableHeaderView.m \
        
gui/macosx/library/audio-library/VLCLibraryAudioGroupTableViewDelegate.h \
        
gui/macosx/library/audio-library/VLCLibraryAudioGroupTableViewDelegate.m \
        gui/macosx/library/audio-library/VLCLibraryAudioTableViewDelegate.h \


=====================================
modules/gui/macosx/library/audio-library/VLCLibraryAudioDataSource.h
=====================================
@@ -24,6 +24,7 @@
 
 #import "library/VLCLibraryCollectionViewDataSource.h"
 #import "library/VLCLibraryTableViewDataSource.h"
+#import "library/audio-library/VLCLibraryAudioDataSourceHeaderDelegate.h"
 
 #include "views/iCarousel/iCarousel.h"
 
@@ -60,6 +61,8 @@ extern NSString * const VLCLibraryYearSortDescriptorKey;
 
 extern NSString * const 
VLCLibraryAudioDataSourceDisplayedCollectionChangedNotification;
 
+@class VLCLibraryRepresentedItem;
+
 @interface VLCLibraryAudioDataSource : NSObject 
<VLCLibraryTableViewDataSource, VLCLibraryCollectionViewDataSource, 
iCarouselDataSource>
 
 @property (readwrite, weak) VLCLibraryModel *libraryModel;
@@ -68,6 +71,7 @@ extern NSString * const 
VLCLibraryAudioDataSourceDisplayedCollectionChangedNotif
 @property (readwrite, weak) NSCollectionView *collectionView;
 @property (readwrite, weak) iCarousel *carouselView;
 @property (readwrite, weak) NSTableView *gridModeListTableView;
+@property (readwrite, weak, nullable) 
id<VLCLibraryAudioDataSourceHeaderDelegate> headerDelegate;
 
 @property (nonatomic, readwrite, assign) VLCAudioLibrarySegment 
audioLibrarySegment;
 @property (readwrite, strong) VLCLibraryAudioGroupDataSource 
*audioGroupDataSource;
@@ -80,6 +84,7 @@ extern NSString * const 
VLCLibraryAudioDataSourceDisplayedCollectionChangedNotif
 - (void)setup;
 - (void)reloadData;
 - (void)tableView:(NSTableView * const)tableView selectRowIndices:(NSIndexSet 
* const)indices;
+- (void)applySelectionForTableView:(NSTableView *)tableView;
 
 @end
 


=====================================
modules/gui/macosx/library/audio-library/VLCLibraryAudioDataSource.m
=====================================
@@ -693,6 +693,48 @@ NSString * const 
VLCLibraryAudioDataSourceDisplayedCollectionChangedNotification
     return self.displayedCollection[row];
 }
 
+- (void)applySelectionForTableView:(NSTableView *)tableView
+{
+    if (tableView == nil ||
+        (tableView != self.collectionSelectionTableView && tableView != 
self.gridModeListTableView)) {
+        return;
+    }
+
+    const NSInteger selectedRow = tableView.selectedRow;
+    if (selectedRow >= 0 && (NSUInteger)selectedRow >= 
self.displayedCollection.count) {
+        return;
+    }
+
+    const BOOL shouldClearSelection = self.currentParentType == 
VLCMediaLibraryParentGroupTypeAudioLibrary ||
+                                      self.currentParentType == 
VLCMediaLibraryParentGroupTypeRecentAudios ||
+                                      selectedRow < 0 ||
+                                      self.displayedCollectionUpdating;
+
+    const id<VLCMediaLibraryAudioGroupProtocol> selectedItem =
+        shouldClearSelection ? nil : self.displayedCollection[selectedRow];
+    self.audioGroupDataSource.representedAudioGroup = selectedItem;
+
+    VLCLibraryRepresentedItem *representedItem = nil;
+    NSString *fallbackTitle = nil;
+    NSString *fallbackDetail = nil;
+
+    if (self.displayAllArtistsGenresTableEntry && selectedRow == 0) {
+        fallbackTitle = (self.currentParentType == 
VLCMediaLibraryParentGroupTypeGenre)
+            ? _NS("All genres")
+            : _NS("All artists");
+    } else if (selectedItem != nil) {
+        representedItem = [[VLCLibraryRepresentedItem alloc] 
initWithItem:selectedItem parentType:self.currentParentType];
+        fallbackTitle = selectedItem.displayString;
+        fallbackDetail = selectedItem.primaryDetailString;
+    }
+
+    [self.headerDelegate audioDataSource:self
+                updateHeaderForTableView:tableView
+                     withRepresentedItem:representedItem
+                           fallbackTitle:fallbackTitle
+                          fallbackDetail:fallbackDetail];
+}
+
 - (void)tableView:(NSTableView * const)tableView selectRowIndices:(NSIndexSet 
* const)indices
 {
     NSParameterAssert(tableView);
@@ -711,14 +753,7 @@ NSString * const 
VLCLibraryAudioDataSourceDisplayedCollectionChangedNotification
         return;
     }
 
-    if (self.currentParentType == VLCMediaLibraryParentGroupTypeAudioLibrary ||
-        self.currentParentType == VLCMediaLibraryParentGroupTypeRecentAudios ||
-        selectedRow < 0 ||
-        self.displayedCollectionUpdating) {
-        self.audioGroupDataSource.representedAudioGroup = nil;
-    } else {
-        self.audioGroupDataSource.representedAudioGroup = 
self.displayedCollection[selectedRow];
-    }
+    [self applySelectionForTableView:tableView];
 }
 
 - (void)tableView:(NSTableView *)tableView 
sortDescriptorsDidChange:(NSArray<NSSortDescriptor *> *)oldDescriptors


=====================================
modules/gui/macosx/library/audio-library/VLCLibraryAudioDataSourceHeaderDelegate.h
=====================================
@@ -0,0 +1,40 @@
+/*****************************************************************************
+ * VLCLibraryAudioDataSourceHeaderDelegate.h: MacOS X interface module
+ *****************************************************************************
+ * Copyright (C) 2025 VLC authors and VideoLAN
+ *
+ * Authors: Claudio Cambra <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, 
USA.
+ *****************************************************************************/
+
+#import <Cocoa/Cocoa.h>
+
+@class VLCLibraryAudioDataSource;
+@class VLCLibraryRepresentedItem;
+
+NS_ASSUME_NONNULL_BEGIN
+
+@protocol VLCLibraryAudioDataSourceHeaderDelegate <NSObject>
+
+- (void)audioDataSource:(VLCLibraryAudioDataSource *)dataSource
+    updateHeaderForTableView:(NSTableView *)tableView
+         withRepresentedItem:(VLCLibraryRepresentedItem *)representedItem
+               fallbackTitle:(NSString *)fallbackTitle
+              fallbackDetail:(NSString *)fallbackDetail;
+
+@end
+
+NS_ASSUME_NONNULL_END


=====================================
modules/gui/macosx/library/audio-library/VLCLibraryAudioGroupTableHeaderCell.h
=====================================
@@ -0,0 +1,32 @@
+/*****************************************************************************
+ * VLCLibraryAudioGroupTableHeaderCell.h: MacOS X interface module
+ *****************************************************************************
+ * Copyright (C) 2025 VLC authors and VideoLAN
+ *
+ * Authors: Claudio Cambra <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, 
USA.
+ *****************************************************************************/
+
+#import <Cocoa/Cocoa.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface VLCLibraryAudioGroupTableHeaderCell : NSTableHeaderCell
+
+@end
+
+NS_ASSUME_NONNULL_END
+


=====================================
modules/gui/macosx/library/audio-library/VLCLibraryAudioGroupTableHeaderCell.m
=====================================
@@ -0,0 +1,35 @@
+/*****************************************************************************
+ * VLCLibraryAudioGroupTableHeaderCell.m: MacOS X interface module
+ *****************************************************************************
+ * Copyright (C) 2025 VLC authors and VideoLAN
+ *
+ * Authors: Claudio Cambra <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, 
USA.
+ *****************************************************************************/
+
+#import "VLCLibraryAudioGroupTableHeaderCell.h"
+
+@implementation VLCLibraryAudioGroupTableHeaderCell
+
+- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
+{
+    // Intentionally do not call super to prevent AppKit from drawing its 
default background.
+    // The header view hosts its own background visuals (glass/effect/solid) 
and draws content there.
+    [NSColor.clearColor setFill];
+    NSRectFillUsingOperation(cellFrame, NSCompositingOperationClear);
+}
+
+@end


=====================================
modules/gui/macosx/library/audio-library/VLCLibraryAudioGroupTableHeaderView.h
=====================================
@@ -0,0 +1,41 @@
+/*****************************************************************************
+ * VLCLibraryAudioGroupTableHeaderView.h: MacOS X interface module
+ *****************************************************************************
+ * Copyright (C) 2025 VLC authors and VideoLAN
+ *
+ * Authors: Claudio Cambra <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, 
USA.
+ *****************************************************************************/
+
+#import <Cocoa/Cocoa.h>
+
+@class VLCLibraryRepresentedItem;
+
+NS_ASSUME_NONNULL_BEGIN
+
+extern const CGFloat VLCLibraryAudioGroupTableHeaderViewHeight;
+
+@interface VLCLibraryAudioGroupTableHeaderView : NSTableHeaderView
+
+@property (nullable, nonatomic) VLCLibraryRepresentedItem *representedItem;
+
+- (void)updateWithRepresentedItem:(nullable VLCLibraryRepresentedItem 
*)representedItem
+                    fallbackTitle:(nullable NSString *)fallbackTitle
+                   fallbackDetail:(nullable NSString *)fallbackDetail;
+
+@end
+
+NS_ASSUME_NONNULL_END


=====================================
modules/gui/macosx/library/audio-library/VLCLibraryAudioGroupTableHeaderView.m
=====================================
@@ -0,0 +1,268 @@
+/*****************************************************************************
+ * VLCLibraryAudioGroupTableHeaderView.m: MacOS X interface module
+ *****************************************************************************
+ * Copyright (C) 2025 VLC authors and VideoLAN
+ *
+ * Authors: Claudio Cambra <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, 
USA.
+ *****************************************************************************/
+
+#import "VLCLibraryAudioGroupTableHeaderView.h"
+
+#import "library/VLCLibraryRepresentedItem.h"
+#import "library/VLCLibraryUIUnits.h"
+
+#import "extensions/NSColor+VLCAdditions.h"
+#import "extensions/NSFont+VLCAdditions.h"
+#import "extensions/NSString+Helpers.h"
+
+const CGFloat VLCLibraryAudioGroupTableHeaderViewHeight = 86.f;
+
+@interface VLCLibraryAudioGroupTableHeaderView ()
+
+@property NSView *backgroundView;
+@property NSStackView *rootStackView;
+@property NSStackView *labelsStackView;
+@property NSStackView *buttonsStackView;
+@property NSTextField *titleField;
+@property NSTextField *detailField;
+@property NSButton *playButton;
+@property NSButton *queueButton;
+@property CGFloat backgroundEdgeInset;
+
+@end
+
+@implementation VLCLibraryAudioGroupTableHeaderView
+
+- (instancetype)initWithFrame:(NSRect)frameRect
+{
+    self = [super initWithFrame:frameRect];
+    if (self) {
+        [self commonInit];
+    }
+    return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)coder
+{
+    self = [super initWithCoder:coder];
+    if (self) {
+        [self commonInit];
+    }
+    return self;
+}
+
+
+- (void)commonInit
+{
+    NSView *contentHostView = self;
+    self.backgroundEdgeInset = 0.f;
+
+#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 260000
+    if (@available(macOS 26.0, *)) {
+        NSGlassEffectView * const glassView = [[NSGlassEffectView alloc] 
initWithFrame:self.bounds];
+        glassView.translatesAutoresizingMaskIntoConstraints = NO;
+        NSView * const glassContentView = [[NSView alloc] 
initWithFrame:glassView.bounds];
+        glassContentView.translatesAutoresizingMaskIntoConstraints = NO;
+        glassView.contentView = glassContentView;
+        self.backgroundView = glassView;
+        contentHostView = glassContentView;
+        self.backgroundEdgeInset = VLCLibraryUIUnits.largeSpacing * 1.75;
+    }
+#endif
+    if (self.backgroundView == nil) {
+        self.wantsLayer = YES;
+
+        if (@available(macOS 10.14, *)) {
+            NSVisualEffectView * const visualEffectView = [[NSVisualEffectView 
alloc] initWithFrame:self.bounds];
+            visualEffectView.translatesAutoresizingMaskIntoConstraints = NO;
+            visualEffectView.material = NSVisualEffectMaterialHeaderView;
+            visualEffectView.blendingMode = 
NSVisualEffectBlendingModeWithinWindow;
+            visualEffectView.state = 
NSVisualEffectStateFollowsWindowActiveState;
+            self.backgroundView = visualEffectView;
+        }
+    }
+    if (self.backgroundView == nil) {
+        NSView * const fallbackBackgroundView = [[NSView alloc] 
initWithFrame:self.bounds];
+        fallbackBackgroundView.translatesAutoresizingMaskIntoConstraints = NO;
+        fallbackBackgroundView.wantsLayer = YES;
+        fallbackBackgroundView.layer.backgroundColor = 
NSColor.windowBackgroundColor.CGColor;
+        self.backgroundView = fallbackBackgroundView;
+    }
+
+    [self addSubview:self.backgroundView];
+
+    self.titleField = [self 
buildLabelWithFont:NSFont.VLClibrarySectionHeaderFont
+                                      textColor:NSColor.labelColor
+                                      alignment:NSTextAlignmentLeft];
+    self.detailField = [self 
buildLabelWithFont:NSFont.VLCLibrarySubsectionSubheaderFont
+                                       textColor:NSColor.secondaryLabelColor
+                                       alignment:NSTextAlignmentLeft];
+    self.playButton = [self buildActionButtonWithTitle:_NS("Play") 
action:@selector(play:)];
+    self.queueButton = [self buildActionButtonWithTitle:_NS("Queue") 
action:@selector(enqueue:)];
+
+    NSStackView * const labelsStack = [NSStackView 
stackViewWithViews:@[self.titleField, self.detailField]];
+    labelsStack.translatesAutoresizingMaskIntoConstraints = NO;
+    labelsStack.orientation = NSUserInterfaceLayoutOrientationVertical;
+    labelsStack.alignment = NSLayoutAttributeLeading;
+    labelsStack.spacing = VLCLibraryUIUnits.smallSpacing;
+    [labelsStack setContentHuggingPriority:NSLayoutPriorityDefaultLow 
forOrientation:NSLayoutConstraintOrientationHorizontal];
+    [labelsStack 
setContentCompressionResistancePriority:NSLayoutPriorityRequired 
forOrientation:NSLayoutConstraintOrientationHorizontal];
+    self.labelsStackView = labelsStack;
+
+    NSStackView * const buttonsStack = [NSStackView 
stackViewWithViews:@[self.playButton, self.queueButton]];
+    buttonsStack.translatesAutoresizingMaskIntoConstraints = NO;
+    buttonsStack.orientation = NSUserInterfaceLayoutOrientationHorizontal;
+    buttonsStack.alignment = NSLayoutAttributeCenterY;
+    buttonsStack.spacing = VLCLibraryUIUnits.smallSpacing;
+    [buttonsStack setContentHuggingPriority:NSLayoutPriorityRequired 
forOrientation:NSLayoutConstraintOrientationHorizontal];
+    [buttonsStack 
setContentCompressionResistancePriority:NSLayoutPriorityRequired 
forOrientation:NSLayoutConstraintOrientationHorizontal];
+    self.buttonsStackView = buttonsStack;
+
+    [contentHostView addSubview:labelsStack];
+    [contentHostView addSubview:buttonsStack];
+
+    const CGFloat backgroundInset = self.backgroundEdgeInset;
+    const CGFloat horizontalContentInset = VLCLibraryUIUnits.mediumSpacing;
+    const CGFloat verticalContentInset = VLCLibraryUIUnits.smallSpacing;
+
+    [NSLayoutConstraint activateConstraints:@[
+        [self.backgroundView.topAnchor constraintEqualToAnchor:self.topAnchor 
constant:backgroundInset * 0.66],
+        [self.backgroundView.leadingAnchor 
constraintEqualToAnchor:self.leadingAnchor],
+        [self.backgroundView.trailingAnchor 
constraintEqualToAnchor:self.trailingAnchor],
+        [self.backgroundView.bottomAnchor 
constraintEqualToAnchor:self.bottomAnchor constant:-backgroundInset],
+        [labelsStack.leadingAnchor 
constraintEqualToAnchor:contentHostView.leadingAnchor 
constant:horizontalContentInset],
+        [labelsStack.centerYAnchor 
constraintEqualToAnchor:contentHostView.centerYAnchor],
+        [contentHostView.trailingAnchor 
constraintEqualToAnchor:buttonsStack.trailingAnchor 
constant:horizontalContentInset],
+        [buttonsStack.centerYAnchor 
constraintEqualToAnchor:contentHostView.centerYAnchor],
+        [buttonsStack.leadingAnchor 
constraintGreaterThanOrEqualToAnchor:labelsStack.trailingAnchor 
constant:VLCLibraryUIUnits.largeSpacing],
+    ]];
+
+    if (@available(macOS 26.0, *)) {
+    } else {
+        self.layer.cornerRadius = VLCLibraryUIUnits.smallSpacing;
+        self.layer.masksToBounds = YES;
+        self.layer.borderWidth = VLCLibraryUIUnits.borderThickness;
+        [self updateAppearance];
+    }
+}
+
+- (NSTextField *)buildLabelWithFont:(NSFont *)font textColor:(NSColor *)color 
alignment:(NSTextAlignment)alignment
+{
+    NSTextField *label;
+    if (@available(macOS 10.12, *)) {
+        label = [NSTextField labelWithString:@""];
+    } else {
+        label = [[NSTextField alloc] initWithFrame:NSZeroRect];
+        label.editable = NO;
+        label.bezeled = NO;
+        label.drawsBackground = NO;
+        label.selectable = NO;
+    }
+    label.font = font;
+    label.textColor = color;
+    label.alignment = alignment;
+    label.lineBreakMode = NSLineBreakByTruncatingTail;
+    label.translatesAutoresizingMaskIntoConstraints = NO;
+    return label;
+}
+
+- (NSButton *)buildActionButtonWithTitle:(NSString *)title action:(SEL)selector
+{
+    NSButton *button;
+    if (@available(macOS 10.12, *)) {
+        button = [NSButton buttonWithTitle:title target:self action:selector];
+    } else {
+        button = [[NSButton alloc] initWithFrame:NSZeroRect];
+        button.title = title;
+        button.target = self;
+        button.action = selector;
+    }
+    button.bezelStyle = NSBezelStyleRounded;
+    button.translatesAutoresizingMaskIntoConstraints = NO;
+    if (@available(macOS 10.14, *))
+        button.contentTintColor = NSColor.VLCAccentColor;
+    return button;
+}
+
+- (void)updateAppearance
+{
+    if (@available(macOS 26.0, *))
+        return;
+
+    if (@available(macOS 10.14, *)) {
+        NSAppearance *appearance = self.effectiveAppearance;
+        BOOL isDark = NO;
+        if ([appearance.name isEqualToString:NSAppearanceNameDarkAqua] ||
+            [appearance.name isEqualToString:NSAppearanceNameVibrantDark]) {
+            isDark = YES;
+        }
+        self.layer.borderColor = (isDark ? NSColor.VLCDarkSubtleBorderColor : 
NSColor.VLCLightSubtleBorderColor).CGColor;
+    } else {
+        self.layer.borderColor = NSColor.VLCLightSubtleBorderColor.CGColor;
+    }
+}
+
+- (void)viewDidChangeEffectiveAppearance
+{
+    [super viewDidChangeEffectiveAppearance];
+    [self updateAppearance];
+}
+
+- (void)setRepresentedItem:(VLCLibraryRepresentedItem *)representedItem
+{
+    _representedItem = representedItem;
+    [self applyRepresentedItemWithFallbackTitle:nil fallbackDetail:nil];
+}
+
+- (void)applyRepresentedItemWithFallbackTitle:(NSString *)fallbackTitle 
fallbackDetail:(NSString *)fallbackDetail
+{
+    id<VLCMediaLibraryItemProtocol> const item = self.representedItem.item;
+    if (item == nil) {
+        self.titleField.stringValue = fallbackTitle ?: @"";
+        self.detailField.stringValue = fallbackDetail ?: @"";
+        self.playButton.enabled = NO;
+        self.queueButton.enabled = NO;
+        return;
+    }
+
+    self.titleField.stringValue = item.displayString ?: fallbackTitle ?: @"";
+    self.detailField.stringValue = item.primaryDetailString ?: fallbackDetail 
?: @"";
+    self.playButton.enabled = YES;
+    self.queueButton.enabled = YES;
+}
+
+- (void)updateWithRepresentedItem:(VLCLibraryRepresentedItem *)representedItem
+                    fallbackTitle:(NSString *)fallbackTitle
+                   fallbackDetail:(NSString *)fallbackDetail
+{
+    self.representedItem = representedItem;
+    [self applyRepresentedItemWithFallbackTitle:fallbackTitle 
fallbackDetail:fallbackDetail];
+}
+
+#pragma mark - Actions
+
+- (void)play:(id)sender
+{
+    [self.representedItem play];
+}
+
+- (void)enqueue:(id)sender
+{
+    [self.representedItem queue];
+}
+
+@end


=====================================
modules/gui/macosx/library/audio-library/VLCLibraryAudioViewController.h
=====================================
@@ -25,9 +25,11 @@
 #import "library/VLCLibrarySegment.h"
 #import "library/VLCLibraryAbstractMediaLibrarySegmentViewController.h"
 #import "library/VLCLibraryItemPresentingCapable.h"
+#import "library/audio-library/VLCLibraryAudioDataSourceHeaderDelegate.h"
 
 @class VLCLibraryAudioDataSource;
 @class VLCLibraryAudioGroupDataSource;
+@class VLCLibraryAudioGroupTableHeaderView;
 @class VLCLibraryCollectionView;
 @class VLCLibraryWindow;
 
@@ -35,12 +37,13 @@
 
 NS_ASSUME_NONNULL_BEGIN
 
-@interface VLCLibraryAudioViewController : 
VLCLibraryAbstractMediaLibrarySegmentViewController<VLCLibraryItemPresentingCapable>
+@interface VLCLibraryAudioViewController : 
VLCLibraryAbstractMediaLibrarySegmentViewController<VLCLibraryItemPresentingCapable,
 VLCLibraryAudioDataSourceHeaderDelegate>
 
 @property (readonly, weak) NSView *audioLibraryView;
 @property (readonly, weak) NSSplitView *audioLibrarySplitView;
 @property (readonly, weak) NSScrollView 
*audioCollectionSelectionTableViewScrollView;
 @property (readonly, weak) NSTableView *audioCollectionSelectionTableView;
+@property (readonly, strong) VLCLibraryAudioGroupTableHeaderView 
*audioCollectionHeaderView;
 @property (readonly, weak) NSScrollView 
*audioGroupSelectionTableViewScrollView;
 @property (readonly, weak) NSTableView *audioGroupSelectionTableView;
 @property (readonly, weak) NSScrollView *audioSongTableViewScrollView;


=====================================
modules/gui/macosx/library/audio-library/VLCLibraryAudioViewController.m
=====================================
@@ -42,7 +42,9 @@
 #import "library/audio-library/VLCLibraryAudioDataSource.h"
 #import "library/audio-library/VLCLibraryAudioGroupDataSource.h"
 #import "library/audio-library/VLCLibraryAudioGroupHeaderView.h"
+#import "library/audio-library/VLCLibraryAudioGroupTableHeaderView.h"
 #import "library/audio-library/VLCLibraryAudioGroupTableViewDelegate.h"
+#import "library/audio-library/VLCLibraryAudioGroupTableHeaderCell.h"
 #import "library/audio-library/VLCLibraryAudioTableViewDelegate.h"
 
 #import "library/playlist-library/VLCLibraryPlaylistViewController.h"
@@ -159,6 +161,7 @@ NSString *VLCLibraryPlaceholderAudioViewIdentifier = 
@"VLCLibraryPlaceholderAudi
     _audioDataSource.songsTableView = _audioSongTableView;
     _audioDataSource.collectionView = _audioLibraryCollectionView;
     _audioDataSource.gridModeListTableView = 
_audioLibraryGridModeSplitViewListTableView;
+    _audioDataSource.headerDelegate = self;
     [_audioDataSource setup];
 
     _audioGroupDataSource = [[VLCLibraryAudioGroupDataSource alloc] init];
@@ -185,6 +188,21 @@ NSString *VLCLibraryPlaceholderAudioViewIdentifier = 
@"VLCLibraryPlaceholderAudi
     _audioCollectionSelectionTableView.dataSource = _audioDataSource;
     _audioCollectionSelectionTableView.delegate = 
_audioLibraryTableViewDelegate;
 
+    CGFloat headerHeight = VLCLibraryAudioGroupTableHeaderViewHeight;
+    if (@available(macOS 26.0, *)) {
+        headerHeight += VLCLibraryUIUnits.largeSpacing * 2.f;
+    }
+
+    const NSRect headerFrame = NSMakeRect(0.f,
+                                          0.f,
+                                          
_audioGroupSelectionTableView.bounds.size.width,
+                                          headerHeight);
+    _audioCollectionHeaderView = [[VLCLibraryAudioGroupTableHeaderView alloc] 
initWithFrame:headerFrame];
+    _audioCollectionHeaderView.autoresizingMask = NSViewWidthSizable;
+
+    _audioGroupSelectionTableView.headerView = self.audioCollectionHeaderView;
+    _audioGroupSelectionTableView.tableColumns.firstObject.headerCell = 
[VLCLibraryAudioGroupTableHeaderCell new];
+
     _audioGroupSelectionTableView.dataSource = _audioGroupDataSource;
     _audioGroupSelectionTableView.delegate = 
_audioGroupLibraryTableViewDelegate;
 
@@ -194,6 +212,8 @@ NSString *VLCLibraryPlaceholderAudioViewIdentifier = 
@"VLCLibraryPlaceholderAudi
 
     _audioSongTableView.dataSource = _audioDataSource;
     _audioSongTableView.delegate = _audioLibraryTableViewDelegate;
+
+    [_audioDataSource 
applySelectionForTableView:_audioCollectionSelectionTableView];
 }
 
 - (void)setupGridModeSplitView
@@ -565,4 +585,24 @@ NSString *VLCLibraryPlaceholderAudioViewIdentifier = 
@"VLCLibraryPlaceholderAudi
     [self.libraryWindow hideLoadingOverlay];
 }
 
+- (void)audioDataSource:(VLCLibraryAudioDataSource *)dataSource
+updateHeaderForTableView:(NSTableView *)tableView
+    withRepresentedItem:(VLCLibraryRepresentedItem *)representedItem
+          fallbackTitle:(NSString *)fallbackTitle
+         fallbackDetail:(NSString *)fallbackDetail
+{
+    if (tableView != self.audioCollectionSelectionTableView &&
+        tableView != self.audioGroupSelectionTableView &&
+        ![self.audioGroupDataSource.tableViews containsObject:tableView])
+        return;
+
+    if (representedItem != nil) {
+        self.audioCollectionHeaderView.representedItem = representedItem;
+    } else {
+        [self.audioCollectionHeaderView updateWithRepresentedItem:nil
+                                                    fallbackTitle:fallbackTitle
+                                                   
fallbackDetail:fallbackDetail];
+    }
+}
+
 @end



View it on GitLab: 
https://code.videolan.org/videolan/vlc/-/compare/31b9abc49c938252c24c05871468df5444ea4bed...05f437f98ec2b830315fe11e837049c227bf3662

-- 
View it on GitLab: 
https://code.videolan.org/videolan/vlc/-/compare/31b9abc49c938252c24c05871468df5444ea4bed...05f437f98ec2b830315fe11e837049c227bf3662
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance
_______________________________________________
vlc-commits mailing list
[email protected]
https://mailman.videolan.org/listinfo/vlc-commits

Reply via email to