diff --git a/modules/gui/macosx/UI/VLCLibraryWindow.xib b/modules/gui/macosx/UI/VLCLibraryWindow.xib index ce75a54a5b32d5aaa7736a40e3f378d415bc73f3..c24ca5c6b9a59823a3b012c280a3df57d8ff210a 100644 --- a/modules/gui/macosx/UI/VLCLibraryWindow.xib +++ b/modules/gui/macosx/UI/VLCLibraryWindow.xib @@ -155,6 +155,35 @@ <action selector="clearPlaylist:" target="QvC-M9-y7g" id="tzd-mR-sDu"/> </connections> </button> + <customView hidden="YES" translatesAutoresizingMaskIntoConstraints="NO" id="VFI-oW-dMZ" customClass="VLCDragDropView"> + <rect key="frame" x="0.0" y="55" width="237" height="195"/> + <subviews> + <imageView translatesAutoresizingMaskIntoConstraints="NO" id="cTV-Wf-TfJ" customClass="VLCDropDisabledImageView"> + <rect key="frame" x="63" y="42" width="112" height="112"/> + <constraints> + <constraint firstAttribute="width" constant="112" id="IvG-i0-rbs"/> + <constraint firstAttribute="height" constant="112" id="dO8-Iv-pDk"/> + </constraints> + <imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="dropzone" id="sHO-XQ-hCU"/> + </imageView> + <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="SWh-4E-Qtf"> + <rect key="frame" x="56" y="4" width="125" height="32"/> + <buttonCell key="cell" type="push" title="Open media..." bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="UUH-HF-Iqc"> + <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> + <font key="font" metaFont="system"/> + </buttonCell> + <connections> + <action selector="openMedia:" target="QvC-M9-y7g" id="Px5-M7-DSb"/> + </connections> + </button> + </subviews> + <constraints> + <constraint firstItem="cTV-Wf-TfJ" firstAttribute="centerY" secondItem="VFI-oW-dMZ" secondAttribute="centerY" id="OHT-tO-cJy"/> + <constraint firstItem="SWh-4E-Qtf" firstAttribute="top" secondItem="cTV-Wf-TfJ" secondAttribute="bottom" constant="10" id="eok-CR-lus"/> + <constraint firstItem="cTV-Wf-TfJ" firstAttribute="centerX" secondItem="VFI-oW-dMZ" secondAttribute="centerX" id="sOt-js-AM3"/> + <constraint firstItem="SWh-4E-Qtf" firstAttribute="centerX" secondItem="cTV-Wf-TfJ" secondAttribute="centerX" id="xrf-SM-XAK"/> + </constraints> + </customView> </subviews> <constraints> <constraint firstItem="Vry-OZ-ySI" firstAttribute="leading" secondItem="dus-WQ-AmE" secondAttribute="leading" constant="20" id="6iz-2G-xXO"/> @@ -163,8 +192,10 @@ <constraint firstItem="nAW-KH-ipk" firstAttribute="leading" secondItem="dus-WQ-AmE" secondAttribute="leading" constant="20" id="EUp-9J-Fid"/> <constraint firstItem="Z7y-D0-11Q" firstAttribute="top" secondItem="qmL-Ar-cj1" secondAttribute="bottom" constant="8" id="GIh-g3-rqJ"/> <constraint firstItem="Z7y-D0-11Q" firstAttribute="leading" secondItem="dus-WQ-AmE" secondAttribute="leading" constant="20" id="J3s-se-6bL"/> + <constraint firstItem="VFI-oW-dMZ" firstAttribute="top" secondItem="qmL-Ar-cj1" secondAttribute="bottom" id="JzJ-oS-dIb"/> <constraint firstItem="Vry-OZ-ySI" firstAttribute="top" secondItem="dus-WQ-AmE" secondAttribute="top" id="K80-Vw-FfD"/> <constraint firstItem="8zF-Wo-H79" firstAttribute="centerY" secondItem="jg5-33-vH0" secondAttribute="centerY" id="Qdp-7K-RkD"/> + <constraint firstAttribute="trailing" secondItem="VFI-oW-dMZ" secondAttribute="trailing" id="YeE-gw-hV0"/> <constraint firstItem="Z7y-D0-11Q" firstAttribute="baseline" secondItem="nAW-KH-ipk" secondAttribute="firstBaseline" constant="-8" id="ZIg-X2-w2p"/> <constraint firstAttribute="trailing" secondItem="cih-xp-HmY" secondAttribute="trailing" constant="20" id="ZmV-zc-4a0"/> <constraint firstItem="8zF-Wo-H79" firstAttribute="leading" secondItem="jg5-33-vH0" secondAttribute="trailing" constant="20" id="aAn-lh-NcZ"/> @@ -174,6 +205,8 @@ <constraint firstItem="qmL-Ar-cj1" firstAttribute="leading" secondItem="dus-WQ-AmE" secondAttribute="leading" constant="20" id="st7-tK-qLh"/> <constraint firstAttribute="trailing" secondItem="Z7y-D0-11Q" secondAttribute="trailing" id="x0A-xI-BVt"/> <constraint firstItem="jg5-33-vH0" firstAttribute="firstBaseline" secondItem="cih-xp-HmY" secondAttribute="firstBaseline" id="xwe-Nb-2Rz"/> + <constraint firstItem="VFI-oW-dMZ" firstAttribute="leading" secondItem="dus-WQ-AmE" secondAttribute="leading" id="y24-g1-nh1"/> + <constraint firstItem="nAW-KH-ipk" firstAttribute="top" secondItem="VFI-oW-dMZ" secondAttribute="bottom" id="yZy-ia-HIz"/> <constraint firstAttribute="bottom" secondItem="nAW-KH-ipk" secondAttribute="bottom" constant="54" id="z8O-Xk-fS8"/> <constraint firstItem="jg5-33-vH0" firstAttribute="leading" secondItem="dus-WQ-AmE" secondAttribute="leading" constant="20" id="zEw-GJ-NfA"/> </constraints> @@ -326,6 +359,8 @@ <outlet property="mainSplitView" destination="u8g-jy-S4e" id="lI5-wR-kef"/> <outlet property="mediaSourceCollectionView" destination="r7v-GI-W1U" id="3JJ-GU-o5o"/> <outlet property="mediaSourceScrollView" destination="cFG-c9-cI9" id="gRO-Y7-kdb"/> + <outlet property="openMediaButton" destination="SWh-4E-Qtf" id="sIZ-xo-GLA"/> + <outlet property="playlistDragDropView" destination="VFI-oW-dMZ" id="gVc-mu-f8T"/> <outlet property="playlistTableView" destination="Fr1-af-8gb" id="yaB-Ab-jrx"/> <outlet property="recentVideoLibraryCollectionView" destination="hnE-Hj-MZo" id="Fko-5v-1bC"/> <outlet property="repeatPlaylistButton" destination="8zF-Wo-H79" id="6bH-HF-arx"/> @@ -706,6 +741,7 @@ <resources> <image name="backward-3btns" width="29" height="23"/> <image name="backward-3btns-pressed" width="29" height="23"/> + <image name="dropzone" width="112" height="112"/> <image name="forward-3btns" width="29" height="23"/> <image name="forward-3btns-pressed" width="29" height="23"/> <image name="fullscreen-one-button" width="29" height="23"/> diff --git a/modules/gui/macosx/library/VLCLibraryWindow.h b/modules/gui/macosx/library/VLCLibraryWindow.h index 29b7f1450579356873c0c0d1c2e6021658a4e25f..b42394ab9bba2548e6ab4eea4394d53b3722bae1 100644 --- a/modules/gui/macosx/library/VLCLibraryWindow.h +++ b/modules/gui/macosx/library/VLCLibraryWindow.h @@ -24,6 +24,8 @@ NS_ASSUME_NONNULL_BEGIN +@class VLCDragDropView; + @interface VLCLibraryWindowController : NSWindowController - (instancetype)initWithLibraryWindow; @@ -46,6 +48,8 @@ NS_ASSUME_NONNULL_BEGIN @property (readwrite, weak) IBOutlet NSView *libraryTargetView; @property (readwrite, weak) IBOutlet NSTableView *playlistTableView; @property (readwrite, weak) IBOutlet NSTextField *upNextLabel; +@property (readwrite, weak) IBOutlet VLCDragDropView *playlistDragDropView; +@property (readwrite, weak) IBOutlet NSButton *openMediaButton; @property (readwrite, weak) IBOutlet NSBox *upNextSeparator; @property (readwrite, weak) IBOutlet NSButton *clearPlaylistButton; @property (readwrite, weak) IBOutlet NSBox *clearPlaylistSeparator; @@ -66,6 +70,7 @@ NS_ASSUME_NONNULL_BEGIN - (IBAction)shuffleAction:(id)sender; - (IBAction)repeatAction:(id)sender; - (IBAction)clearPlaylist:(id)sender; +- (IBAction)openMedia:(id)sender; @end diff --git a/modules/gui/macosx/library/VLCLibraryWindow.m b/modules/gui/macosx/library/VLCLibraryWindow.m index e0d902078326320f4752052028709426586abec3..681e024bd9ad77a326b714dac01efcaca76cabc3 100644 --- a/modules/gui/macosx/library/VLCLibraryWindow.m +++ b/modules/gui/macosx/library/VLCLibraryWindow.m @@ -41,10 +41,16 @@ #import "media-source/VLCMediaSourceCollectionViewItem.h" #import "media-source/VLCMediaSourceDataSource.h" +#import "views/VLCDragDropView.h" + #import "windows/mainwindow/VLCControlsBarCommon.h" #import "windows/video/VLCFSPanelController.h" #import "windows/video/VLCVoutView.h" #import "windows/video/VLCVideoOutputProvider.h" +#import "windows/VLCOpenWindowController.h" +#import "windows/VLCOpenInputMetadata.h" + +#import <vlc_url.h> const CGFloat VLCLibraryWindowMinimalWidth = 604.; const CGFloat VLCLibraryWindowMinimalHeight = 307.; @@ -52,7 +58,7 @@ const CGFloat VLCLibraryWindowPlaylistRowHeight = 72.; const CGFloat VLCLibraryWindowSmallRowHeight = 24.; const CGFloat VLCLibraryWindowLargeRowHeight = 50.; -@interface VLCLibraryWindow () +@interface VLCLibraryWindow () <VLCDragDropTarget> { VLCPlaylistDataSource *_playlistDataSource; VLCLibraryVideoDataSource *_libraryVideoDataSource; @@ -132,9 +138,12 @@ const CGFloat VLCLibraryWindowLargeRowHeight = 50.; [_segmentedTitleControl sizeToFit]; [_segmentedTitleControl setSelectedSegment:0]; + _playlistDragDropView.dropTarget = self; + _playlistDataSource = [[VLCPlaylistDataSource alloc] init]; _playlistDataSource.playlistController = _playlistController; _playlistDataSource.tableView = _playlistTableView; + _playlistDataSource.dragDropView = _playlistDragDropView; _playlistController.playlistDataSource = _playlistDataSource; _playlistTableView.dataSource = _playlistDataSource; @@ -187,6 +196,7 @@ const CGFloat VLCLibraryWindowLargeRowHeight = 50.; NSForegroundColorAttributeName : [NSColor VLClibraryHighlightColor]}]; self.clearPlaylistButton.attributedTitle = attributedTitle; [self updateColorsBasedOnAppearance]; + self.openMediaButton.title = _NS("Open media..."); _alternativeAudioViewController = [[VLCLibraryAlternativeAudioViewController alloc] init]; _alternativeAudioViewController.collectionView = self.alternativeAudioCollectionView; @@ -386,6 +396,41 @@ const CGFloat VLCLibraryWindowLargeRowHeight = 50.; [_playlistController clearPlaylist]; } +- (IBAction)openMedia:(id)sender +{ + [[[VLCMain sharedInstance] open] openFileGeneric]; +} + +- (BOOL)handlePasteBoardFromDragSession:(NSPasteboard *)paste +{ + id propertyList = [paste propertyListForType:NSFilenamesPboardType]; + if (propertyList == nil) { + return NO; + } + + NSArray *values = [propertyList sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]; + NSUInteger valueCount = [values count]; + if (valueCount > 0) { + NSMutableArray *metadataArray = [NSMutableArray arrayWithCapacity:valueCount]; + + for (NSUInteger i = 0; i < valueCount; i++) { + VLCOpenInputMetadata *inputMetadata; + char *psz_uri = vlc_path2uri([values[i] UTF8String], "file"); + if (!psz_uri) + continue; + inputMetadata = [[VLCOpenInputMetadata alloc] init]; + inputMetadata.MRLString = toNSStr(psz_uri); + free(psz_uri); + [metadataArray addObject:inputMetadata]; + } + [_playlistController addPlaylistItems:metadataArray]; + + return YES; + } + + return NO; +} + #pragma mark - video output controlling - (void)videoPlaybackWillBeStarted diff --git a/modules/gui/macosx/playlist/VLCPlaylistDataSource.h b/modules/gui/macosx/playlist/VLCPlaylistDataSource.h index 8dab982c68b1bba429501a9d02f73d37f11ec141..73a778b50207f7fab33f21aef16dffe09dd69dde 100644 --- a/modules/gui/macosx/playlist/VLCPlaylistDataSource.h +++ b/modules/gui/macosx/playlist/VLCPlaylistDataSource.h @@ -23,6 +23,7 @@ #import <Cocoa/Cocoa.h> @class VLCPlaylistController; +@class VLCDragDropView; NS_ASSUME_NONNULL_BEGIN @@ -30,6 +31,7 @@ NS_ASSUME_NONNULL_BEGIN @property (readwrite, assign, nonatomic) VLCPlaylistController *playlistController; @property (readwrite, assign) NSTableView *tableView; +@property (readwrite, assign) VLCDragDropView *dragDropView; - (void)playlistUpdated; diff --git a/modules/gui/macosx/playlist/VLCPlaylistDataSource.m b/modules/gui/macosx/playlist/VLCPlaylistDataSource.m index 61ef4bee6d56eed4984e0c851410b5bc7f7b0f62..5f65f50328b96883f59006542fecb9d5817808d7 100644 --- a/modules/gui/macosx/playlist/VLCPlaylistDataSource.m +++ b/modules/gui/macosx/playlist/VLCPlaylistDataSource.m @@ -28,6 +28,7 @@ #import "playlist/VLCPlaylistTableCellView.h" #import "playlist/VLCPlaylistItem.h" #import "playlist/VLCPlaylistModel.h" +#import "views/VLCDragDropView.h" #import "views/VLCImageView.h" static NSString *VLCPlaylistCellIdentifier = @"VLCPlaylistCellIdentifier"; @@ -102,6 +103,8 @@ static NSString *VLCPlaylistCellIdentifier = @"VLCPlaylistCellIdentifier"; - (void)playlistUpdated { + self.dragDropView.hidden = _playlistModel.numberOfPlaylistItems > 0 ? YES : NO; + [_tableView reloadData]; }