Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/VLC/modules/gui/macosx/library/   (VLC Media Plyer ©)  Datei vom 23.9.2026 mit Größe 10 kB image not shown  

Quelle  VLCLibraryCollectionViewItem.m  Sprache: unbekannt

 
Spracherkennung für: .m vermutete Sprache: Masm {Masm[54] Cobol[44] Python[40]} [Methode: maximale Elemente, drei Dimensionen]

/*****************************************************************************
 * VLCLibraryCollectionViewItem.m: MacOS X interface module
 *****************************************************************************
 * Copyright (C) 2026 VLC authors and VideoLAN
 *
 * Authors: Felix Paul Kühne <fkuehne # videolan -dot- org>
 *          Claudio Cambra <developer@claudiocambra.com>
 *
 * 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 "VLCLibraryCollectionViewItem.h"

#import "extensions/NSColor+VLCAdditions.h"
#import "extensions/NSString+Helpers.h"

#import "library/VLCLibraryCollectionViewDataSource.h"
#import "library/VLCLibraryCollectionViewFlowLayout.h"
#import "library/VLCLibraryDataTypes.h"
#import "library/VLCLibraryImageCache.h"
#import "library/VLCLibraryMenuController.h"
#import "library/VLCLibraryModel.h"
#import "library/VLCLibraryRepresentedItem.h"

#import "views/VLCImageView.h"
#import "views/VLCLinearProgressIndicator.h"
#import "views/VLCMediaItemCollectionViewItem.h"
#import "views/VLCTrackingView.h"

NSString *VLCLibraryCollectionViewItemIdentifier = @"VLCLibraryCollectionViewItemIdentifier";

@interface VLCLibraryCollectionViewItem ()
{
    VLCLibraryMenuController *_menuController;
    NSLayoutConstraint *_videoImageViewAspectRatioConstraint;
}
@end

@implementation VLCLibraryCollectionViewItem

@synthesize representedItem = _representedItem;

- (instancetype)initWithNibName:(NSNibName)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        NSNotificationCenter * const nc = NSNotificationCenter.defaultCenter;
        [nc addObserver:self
               selector:@selector(mediaItemThumbnailGenerated:)
                   name:VLCLibraryModelMediaItemThumbnailGenerated
                 object:nil];
    }
    return self;
}

- (void)dealloc
{
    [NSNotificationCenter.defaultCenter removeObserver:self];
}

- (void)awakeFromNib
{
    self.deselectWhenClickedIfSelected = YES;
    _videoImageViewAspectRatioConstraint = [NSLayoutConstraint constraintWithItem:self.mediaImageView
                                                                        attribute:NSLayoutAttributeHeight
                                                                        relatedBy:NSLayoutRelationEqual
                                                                        toItem:self.mediaImageView
                                                                        attribute:NSLayoutAttributeWidth
                                                                       multiplier:VLCUIUnits.videoItemCollectionViewImageViewAspectRatioMultiplier
                                                                        constant:1];
    _videoImageViewAspectRatioConstraint.priority = NSLayoutPriorityRequired;
    _videoImageViewAspectRatioConstraint.active = NO;

    [super awakeFromNib];

    self.secondaryInfoTextField.textColor = NSColor.VLClibrarySubtitleColor;
    self.unplayedIndicatorTextField.stringValue = _NS("NEW");
    self.unplayedIndicatorTextField.font = [NSFont systemFontOfSize:NSFont.systemFontSize weight:NSFontWeightBold];
    self.unplayedIndicatorTextField.textColor = NSColor.VLCAccentColor;
}

- (void)prepareForReuse
{
    [super prepareForReuse];
    self.secondaryInfoTextField.stringValue = [NSString stringWithTime:0];
    self.progressIndicator.hidden = YES;
    [self setUnplayedIndicatorHidden:YES];
}

- (void)setRepresentedItem:(VLCLibraryRepresentedItem *)representedItem
{
    if (_representedItem == representedItem) {
        return;
    }
    _representedItem = representedItem;
    [self updateRepresentation];
}

- (void)setSelected:(BOOL)selected
{
    [super setSelected:selected];
}

- (void)mediaItemThumbnailGenerated:(NSNotification *)aNotification
{
    VLCMediaLibraryMediaItem * const updatedMediaItem = aNotification.object;
    VLCLibraryRepresentedItem * const representedItem = self.representedItem;
    if (updatedMediaItem == nil || representedItem == nil ||
        ![representedItem.item isKindOfClass:VLCMediaLibraryMediaItem.class]) {
        return;
    }
    VLCMediaLibraryMediaItem * const mediaItem = (VLCMediaLibraryMediaItem *)representedItem.item;
    if (updatedMediaItem.libraryID == mediaItem.libraryID) {
        [self updateRepresentation];
    }
}

- (void)updateRepresentation
{
    VLCLibraryRepresentedItem * const libraryItem = self.representedItem;
    if (libraryItem == nil) {
        return;
    }
    id<VLCMediaLibraryItemProtocol> const actualItem = libraryItem.item;

    self.mediaTitleTextField.stringValue = actualItem.displayString ?: @"";
    self.secondaryInfoTextField.stringValue = actualItem.primaryDetailString ?: @"";
    self.secondaryInfoTextField.hidden = NO;

    __weak typeof(self) weakSelf = self;
    [VLCLibraryImageCache thumbnailForLibraryItem:actualItem
                                   withCompletion:^(NSImage * const thumbnail) {
        __strong typeof(weakSelf) strongSelf = weakSelf;
        if (!strongSelf || strongSelf.representedItem != libraryItem) {
            return;
        }
        strongSelf.mediaImageView.image = thumbnail;
    }];

    if ([actualItem isKindOfClass:VLCMediaLibraryMediaItem.class]) {
        VLCMediaLibraryMediaItem * const mediaItem = (VLCMediaLibraryMediaItem *)actualItem;

        if (mediaItem.mediaType == VLC_ML_MEDIA_TYPE_VIDEO ||
            mediaItem.mediaType == VLC_ML_MEDIA_TYPE_UNKNOWN) {
            VLCMediaLibraryTrack * const videoTrack = mediaItem.firstVideoTrack;
            NSString * const resolutionLabel = videoTrack.resolutionLabel;
            if (resolutionLabel) {
                self.annotationTextField.stringValue = resolutionLabel;
                self.annotationTextField.hidden = NO;
            }
            if (!_videoImageViewAspectRatioConstraint.active) {
                self.imageViewAspectRatioConstraint.active = NO;
                _videoImageViewAspectRatioConstraint.active = YES;
            }
        } else {
            if (_videoImageViewAspectRatioConstraint.active) {
                _videoImageViewAspectRatioConstraint.active = NO;
                self.imageViewAspectRatioConstraint.active = YES;
            }
        }

        const CGFloat position = mediaItem.progress;
        if (position > VLCMediaItemCollectionViewItemMinimalDisplayedProgress &&
            position < VLCMediaItemCollectionViewItemMaximumDisplayedProgress) {
            self.progressIndicator.progress = position;
            self.progressIndicator.hidden = NO;
        }

        if (mediaItem.playCount == 0) {
            [self setUnplayedIndicatorHidden:NO];
        }
    } else {
        self.progressIndicator.hidden = YES;
        if (_videoImageViewAspectRatioConstraint.active) {
            _videoImageViewAspectRatioConstraint.active = NO;
            self.imageViewAspectRatioConstraint.active = YES;
        }
    }
}

- (void)setUnplayedIndicatorHidden:(BOOL)indicatorHidden
{
    if (self.unplayedIndicatorTextField.hidden == indicatorHidden) {
        return;
    }
    self.unplayedIndicatorTextField.hidden = indicatorHidden;
    self.trailingSecondaryTextToLeadingUnplayedIndicatorConstraint.active = !indicatorHidden;
    self.trailingSecondaryTextToTrailingSuperviewConstraint.active = indicatorHidden;
}

#pragma mark - actions

- (IBAction)playInstantly:(id)sender
{
    [self.representedItem play];
}

- (IBAction)addToPlayQueue:(id)sender
{
    [self.representedItem queue];
}

- (void)openContextMenu:(NSEvent *)event
{
    if (!_menuController) {
        _menuController = [[VLCLibraryMenuController alloc] init];
    }
    NSCollectionView * const collectionView = self.collectionView;
    id const dataSource = collectionView.dataSource;
    Protocol * const vlcDataSourceProtocol = @protocol(VLCLibraryCollectionViewDataSource);
    if (![dataSource conformsToProtocol:vlcDataSourceProtocol]) {
        return;
    }
    NSObject<VLCLibraryCollectionViewDataSource> * const libraryDataSource =
        (NSObject<VLCLibraryCollectionViewDataSource> *)dataSource;
    NSSet<NSIndexPath *> * const indexPaths = collectionView.selectionIndexPaths;
    NSArray<VLCLibraryRepresentedItem *> * const selectedItems =
        [libraryDataSource representedItemsAtIndexPaths:indexPaths
                                      forCollectionView:collectionView];
    const NSInteger representedItemIndex = [selectedItems indexOfObjectPassingTest:^BOOL(
        VLCLibraryRepresentedItem * const repItem, const NSUInteger __unused idx, BOOL * const __unused stop
    ) {
        return [repItem isEqual:self.representedItem];
    }];
    NSArray<VLCLibraryRepresentedItem *> *items = nil;
    if (representedItemIndex == NSNotFound) {
        items = @[self.representedItem];
    } else {
        items = selectedItems;
    }
    _menuController.representedItems = items;
    [_menuController popupMenuWithEvent:event forView:self.view];
}

- (void)mouseDown:(NSEvent *)event
{
    if (event.modifierFlags & NSEventModifierFlagControl) {
        [self openContextMenu:event];
        return;
    }
    if (self.deselectWhenClickedIfSelected &&
        self.selected &&
        [self.collectionView.dataSource conformsToProtocol:@protocol(VLCLibraryCollectionViewDataSource)]) {
        NSObject<VLCLibraryCollectionViewDataSource> * const libraryDataSource =
            (NSObject<VLCLibraryCollectionViewDataSource> *)self.collectionView.dataSource;
        NSIndexPath * const indexPath = [libraryDataSource indexPathForLibraryItem:self.representedItem.item];
        if (indexPath == nil) {
            NSLog(@"Received nil indexPath for item %@!", self.representedItem.item.displayString);
            [super mouseDown:event];
            return;
        }
        NSSet<NSIndexPath *> * const indexPathSet = [NSSet setWithObject:indexPath];
        [self.collectionView deselectItemsAtIndexPaths:indexPathSet];
        if ([self.collectionView.collectionViewLayout isKindOfClass:[VLCLibraryCollectionViewFlowLayout class]]) {
            VLCLibraryCollectionViewFlowLayout * const flowLayout =
                (VLCLibraryCollectionViewFlowLayout *)self.collectionView.collectionViewLayout;
            [flowLayout collapseDetailSectionAtIndex:indexPath];
        }
    }
    [super mouseDown:event];
}

@end

[Dauer der Verarbeitung: 0.1 Sekunden, vorverarbeitet 2026-10-24]