Implement copy & paste

This commit is contained in:
Matthias Neeracher 2011-08-22 03:54:09 +02:00
parent 8c9f0ae12d
commit bb4094f238
7 changed files with 133 additions and 19 deletions

View File

@ -38,6 +38,7 @@
- (IBAction)mediaSkipBackward:(id)sender; - (IBAction)mediaSkipBackward:(id)sender;
- (IBAction)mediaSkipForward:(id)sender; - (IBAction)mediaSkipForward:(id)sender;
- (IBAction)toggleMediaPlay:(id)sender; - (IBAction)toggleMediaPlay:(id)sender;
- (IBAction)delete:(id)sender;
- (QTTime)currentMovieTime; - (QTTime)currentMovieTime;
- (void)moviePanelDidAppear; - (void)moviePanelDidAppear;
- (void)moviePanelDidClose; - (void)moviePanelDidClose;

View File

@ -282,6 +282,9 @@ static const char * kMADocWindowObserver = "MADocWindowObserver";
) )
return YES; return YES;
if ([item action] == @selector(paste:))
return [self canPaste];
NSMenuItem * menuItem = (NSMenuItem *)item; NSMenuItem * menuItem = (NSMenuItem *)item;
if ([item action] == @selector(toggleMediaPlay:)) { if ([item action] == @selector(toggleMediaPlay:)) {
if ([currentMovie rate] > 0.0f) if ([currentMovie rate] > 0.0f)

View File

@ -44,8 +44,11 @@
{ {
NSString * path = [url absoluteString]; NSString * path = [url absoluteString];
NSNumber * size; NSNumber * size;
[url getResourceValue:&size forKey:NSURLFileSizeKey error:nil]; int64_t fileSize;
int64_t fileSize = [size longLongValue]; if ([url getResourceValue:&size forKey:NSURLFileSizeKey error:nil])
fileSize = [size longLongValue];
else
fileSize = 0;
NSTimeInterval fileDate = [date timeIntervalSinceReferenceDate]; NSTimeInterval fileDate = [date timeIntervalSinceReferenceDate];
NSManagedObjectContext *moc = [self managedObjectContext]; NSManagedObjectContext *moc = [self managedObjectContext];

View File

@ -9,10 +9,16 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import "MADocWindow.h" #import "MADocWindow.h"
#import "MATagWindow.h" #import "MATagWindow.h"
#import "MAAppController.h"
@interface MADocWindow (Dragging) @interface MADocWindow (Dragging)
- (void)registerOurDragTypes; - (void)registerOurDragTypes;
- (BOOL)canPaste;
- (IBAction)cut:(id)sender;
- (IBAction)copy:(id)sender;
- (IBAction)paste:(id)sender;
@end @end
@ -20,4 +26,7 @@
- (void)registerOurDragTypes; - (void)registerOurDragTypes;
@end - (IBAction)cut:(id)sender;
- (IBAction)copy:(id)sender;
@end

View File

@ -15,12 +15,15 @@
#define kMADragType @"org.aereperennius.medianno" #define kMADragType @"org.aereperennius.medianno"
static NSPointerArray * sValidPasteboardData;
@interface MAPasteboardData : NSObject <NSPasteboardWriting> { @interface MAPasteboardData : NSObject <NSPasteboardWriting> {
NSArray * contents; NSArray * contents;
} }
- (id)initWithArray:(NSArray *)array; - (id)initWithArray:(NSArray *)array;
+ (id)pasteboardDataWithArray:(NSArray *)array; + (id)pasteboardDataWithArray:(NSArray *)array;
+ (NSArray *)arrayFromPasteboard:(NSPasteboard *)pboard;
@end @end
@ -28,8 +31,13 @@
- (id)initWithArray:(NSArray *)array - (id)initWithArray:(NSArray *)array
{ {
if (!sValidPasteboardData)
sValidPasteboardData = [[NSPointerArray alloc] initWithOptions:NSPointerFunctionsZeroingWeakMemory];
self = [super init]; self = [super init];
contents = array; contents = array;
if ([sValidPasteboardData count] > 10)
[sValidPasteboardData compact];
[sValidPasteboardData addPointer:contents];
return self; return self;
} }
@ -39,6 +47,17 @@
return [[[MAPasteboardData alloc] initWithArray:array] autorelease]; return [[[MAPasteboardData alloc] initWithArray:array] autorelease];
} }
+ (NSArray *)arrayFromPasteboard:(NSPasteboard *)pboard
{
if (NSNumber * drag = [pboard propertyListForType:kMADragType]) {
NSArray * possibleArray = (NSArray *)[drag longValue];
for (NSUInteger count = [sValidPasteboardData count]; count--; )
if ([sValidPasteboardData pointerAtIndex:count] == possibleArray)
return possibleArray;
}
return nil;
}
- (NSArray *)writableTypesForPasteboard:(NSPasteboard *)pasteboard - (NSArray *)writableTypesForPasteboard:(NSPasteboard *)pasteboard
{ {
MAMedia * media; MAMedia * media;
@ -96,10 +115,30 @@
return YES; return YES;
} }
- (Class)classOfDraggedObjects:(id)drag - (IBAction)copy:(id)sender
{ {
NSArray * dragObjects = (NSArray *)[drag longValue]; NSPasteboard* pboard = [NSPasteboard pasteboardWithName:NSGeneralPboard];
NSResponder * responder = [[self window] firstResponder];
while (responder && responder != self) {
if (responder == mediaTable) {
[self tableView:mediaTable writeRowsWithIndexes:[mediaController selectionIndexes] toPasteboard:pboard];
break;
} else if (responder == annotationTable) {
[self tableView:annotationTable writeRowsWithIndexes:[annotationController selectionIndexes] toPasteboard:pboard];
break;
}
responder = [responder nextResponder];
}
}
- (IBAction)cut:(id)sender
{
[self copy:sender];
[self delete:sender];
}
- (Class)classOfDraggedObjects:(NSArray *)dragObjects
{
return [dragObjects count] ? [[dragObjects objectAtIndex:0] class] : nil; return [dragObjects count] ? [[dragObjects objectAtIndex:0] class] : nil;
} }
@ -110,9 +149,9 @@
// //
if (tableView == [info draggingSource]) if (tableView == [info draggingSource])
return NSDragOperationNone; return NSDragOperationNone;
NSPasteboard * pb = [info draggingPasteboard]; NSPasteboard * pboard = [info draggingPasteboard];
id drag; id drag;
if ((drag = [pb propertyListForType:kMADragType])) { if ((drag = [MAPasteboardData arrayFromPasteboard:pboard])) {
// //
// We don't allow media drops in annotation table // We don't allow media drops in annotation table
// //
@ -131,11 +170,11 @@
} }
return NSDragOperationCopy; return NSDragOperationCopy;
} else if (tableView == mediaTable) { } else if (tableView == mediaTable) {
if ((drag = [pb propertyListForType:NSFilenamesPboardType])) { if ((drag = [pboard propertyListForType:NSFilenamesPboardType])) {
[tableView setDropRow:row dropOperation:NSTableViewDropAbove]; [tableView setDropRow:row dropOperation:NSTableViewDropAbove];
return NSDragOperationLink; return NSDragOperationLink;
} else if ((drag = [pb stringForType:(NSString *)kUTTypeURL]) } else if ((drag = [pboard stringForType:(NSString *)kUTTypeURL])
|| (drag = [pb stringForType:(NSString *)kUTTypeFileURL]) || (drag = [pboard stringForType:(NSString *)kUTTypeFileURL])
) { ) {
[tableView setDropRow:row dropOperation:NSTableViewDropAbove]; [tableView setDropRow:row dropOperation:NSTableViewDropAbove];
return NSDragOperationLink; return NSDragOperationLink;
@ -146,7 +185,7 @@
- (BOOL)tableView:(NSTableView *)tableView acceptDrop:(id<NSDraggingInfo>)info row:(NSInteger)row dropOperation:(NSTableViewDropOperation)dropOperation - (BOOL)tableView:(NSTableView *)tableView acceptDrop:(id<NSDraggingInfo>)info row:(NSInteger)row dropOperation:(NSTableViewDropOperation)dropOperation
{ {
NSPasteboard * pb = [info draggingPasteboard]; NSPasteboard * pboard = [info draggingPasteboard];
MADocument * doc = [self document]; MADocument * doc = [self document];
MAMedia * media = nil; MAMedia * media = nil;
@ -159,22 +198,69 @@
} }
id drag; id drag;
if ((drag = [pb propertyListForType:kMADragType])) { if ((drag = [MAPasteboardData arrayFromPasteboard:pboard])) {
for (id obj in (NSArray *)[drag longValue]) for (id obj in drag)
[obj copyToDocument:doc withMedia:media]; [obj copyToDocument:doc withMedia:media];
} else if ((drag = [pb propertyListForType:NSFilenamesPboardType])) { } else if ((drag = [pboard propertyListForType:NSFilenamesPboardType])) {
NSMutableArray * urls = [NSMutableArray array]; NSMutableArray * urls = [NSMutableArray array];
for (NSString * path in drag) for (NSString * path in drag)
[urls addObject:[NSURL fileURLWithPath:path]]; [urls addObject:[NSURL fileURLWithPath:path]];
[self addMedia:urls]; [self addMedia:urls];
} else if ((drag = [pb stringForType:(NSString *)kUTTypeURL]) } else if ((drag = [pboard stringForType:(NSString *)kUTTypeURL])
|| (drag = [pb stringForType:(NSString *)kUTTypeFileURL]) || (drag = [pboard stringForType:(NSString *)kUTTypeFileURL])
) { ) {
[self addMedia:[NSArray arrayWithObject:[NSURL URLWithString:drag]]]; [self addMedia:[NSArray arrayWithObject:[NSURL URLWithString:drag]]];
} }
return YES; return YES;
} }
- (IBAction)paste:(id)sender
{
NSPasteboard* pboard = [NSPasteboard pasteboardWithName:NSGeneralPboard];
MADocument * doc = [self document];
NSManagedObjectContext *moc = [doc managedObjectContext];
id drag;
if ((drag = [MAPasteboardData arrayFromPasteboard:pboard])) {
MAMedia * media = [self currentMedia];
for (id obj in drag)
if ([obj managedObjectContext] != moc)
[obj copyToDocument:doc withMedia:media];
} else if ((drag = [pboard propertyListForType:NSFilenamesPboardType])) {
NSMutableArray * urls = [NSMutableArray array];
for (NSString * path in drag)
[urls addObject:[NSURL fileURLWithPath:path]];
[self addMedia:urls];
} else if ((drag = [pboard stringForType:(NSString *)kUTTypeURL])
|| (drag = [pboard stringForType:(NSString *)kUTTypeFileURL])
) {
[self addMedia:[NSArray arrayWithObject:[NSURL URLWithString:drag]]];
}
}
- (BOOL)canPaste
{
NSPasteboard* pboard = [NSPasteboard pasteboardWithName:NSGeneralPboard];
id drag;
if ((drag = [MAPasteboardData arrayFromPasteboard:pboard])) {
MAMedia * media = [self currentMedia];
if (![drag count])
return NO;
id obj = [drag objectAtIndex:0];
if ([obj managedObjectContext] == [[self document] managedObjectContext])
return NO;
else
return [obj class] != [MAAnno class] || media;
} else if ((drag = [pboard propertyListForType:NSFilenamesPboardType])) {
return YES;
} else if ((drag = [pboard stringForType:(NSString *)kUTTypeURL])
|| (drag = [pboard stringForType:(NSString *)kUTTypeFileURL])
) {
return YES;
}
return NO;
}
@end @end
@implementation MATagWindow (Dragging) @implementation MATagWindow (Dragging)
@ -191,9 +277,19 @@
{ {
NSArray * objects = [[tagController arrangedObjects] objectsAtIndexes:rowIndexes]; NSArray * objects = [[tagController arrangedObjects] objectsAtIndexes:rowIndexes];
[pboard clearContents]; [pboard clearContents];
[pboard writeObjects:[NSArray arrayWithObject:[MAPasteboardData pasteboardDataWithArray:objects]]]; [pboard writeObjects:[NSArray arrayWithObject:[MAPasteboardData pasteboardDataWithArray:objects]]];
return YES; return YES;
} }
- (IBAction)copy:(id)sender
{
[self tableView:nil writeRowsWithIndexes:[tagController selectionIndexes] toPasteboard:[NSPasteboard pasteboardWithName:NSGeneralPboard]];
}
- (IBAction)cut:(id)sender
{
[self copy:sender];
[self delete:sender];
}
@end @end

View File

@ -16,6 +16,8 @@
@property (assign) NSDocument * currentDocument; @property (assign) NSDocument * currentDocument;
- (IBAction)toggleWindow:(id)sender; - (IBAction)toggleWindow:(id)sender;
- (IBAction)delete:(id)sender;
- (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item; - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item;
@end @end

View File

@ -48,7 +48,7 @@
if (![self isWindowLoaded] || ![[self window] isVisible]) if (![self isWindowLoaded] || ![[self window] isVisible])
return NO; return NO;
if ([item action] == @selector(delete:)) if ([item action] == @selector(delete:) || [item action] == @selector(cut:) || [item action] == @selector(copy:))
return [tagController selectionIndex] != NSNotFound; return [tagController selectionIndex] != NSNotFound;
return NO; return NO;