diff --git a/MacPass/Base.lproj/InspectorView.xib b/MacPass/Base.lproj/InspectorView.xib index f8054422..4f490d22 100644 --- a/MacPass/Base.lproj/InspectorView.xib +++ b/MacPass/Base.lproj/InspectorView.xib @@ -50,7 +50,6 @@ 268 {{57, 409}, {204, 17}} - _NS:1535 {249, 750} @@ -100,7 +99,6 @@ {{20, 401}, {32, 32}} - _NS:9 YES @@ -126,10 +124,10 @@ - -2147483380 - {{20, 2}, {172, 25}} + 268 + {{20, 2}, {42, 25}} - + _NS:22 YES @@ -139,12 +137,8 @@ _NS:22 - 918306816 + -2034483200 163 - - NSImage - 07_NotepadTemplate - 400 @@ -155,7 +149,6 @@ {278, 30} - _NS:9 HNHGradientView @@ -165,7 +158,7 @@ 12 {{0, 30}, {278, 369}} - + _NS:9 @@ -175,7 +168,7 @@ 256 {278, 369} - + _NS:28 Entry @@ -253,7 +246,6 @@ {278, 443} - _NS:9 NSView @@ -956,110 +948,17 @@ - 3116 - - - - - HNHGradientView - NSView - - IBProjectSource - ./Classes/HNHGradientView.h - - - - MPInspectorViewController - MPViewController - - showImagePopup: - id - - - showImagePopup: - - showImagePopup: - id - - - - HNHGradientView - NSTextField - MPPopupImageView - NSTextField - NSTextField - NSTextField - NSTabView - - - - bottomBar - HNHGradientView - - - createdTextField - NSTextField - - - itemImageView - MPPopupImageView - - - itemNameTextField - NSTextField - - - modifiedTextField - NSTextField - - - noSelectionInfo - NSTextField - - - tabView - NSTabView - - - - IBProjectSource - ./Classes/MPInspectorViewController.h - - - - MPPopupImageView - NSImageView - - IBProjectSource - ./Classes/MPPopupImageView.h - - - - MPViewController - NSViewController - - IBProjectSource - ./Classes/MPViewController.h - - - - NSLayoutConstraint - NSObject - - IBProjectSource - ./Classes/NSLayoutConstraint.h - - - + 3117 + 0 IBCocoaFramework YES 3 - - {128, 128} - {15, 15} - + + NSActionTemplate + {15, 15} + YES diff --git a/MacPass/MPEntryTableDataSource.m b/MacPass/MPEntryTableDataSource.m index 501e52be..3eb3b8c9 100644 --- a/MacPass/MPEntryTableDataSource.m +++ b/MacPass/MPEntryTableDataSource.m @@ -28,8 +28,8 @@ if(![item isKindOfClass:[KPKEntry class]]) { return NO; } - KPKEntry *entry = (KPKEntry *)item; - [pboard writeObjects:@[entry.uuid]]; + KPKEntry *draggedEntry = (KPKEntry *)item; + [pboard writeObjects:@[draggedEntry]]; return YES; } diff --git a/MacPass/MPOutlineDataSource.m b/MacPass/MPOutlineDataSource.m index 67c77440..6ae6a8ec 100644 --- a/MacPass/MPOutlineDataSource.m +++ b/MacPass/MPOutlineDataSource.m @@ -18,8 +18,8 @@ @interface MPOutlineDataSource () -@property (weak) KPKGroup *draggedGroup; -@property (weak) KPKEntry *draggedEntry; +@property (weak) KPKGroup *localDraggedGroup; +@property (weak) KPKEntry *localDraggedEntry; @end @@ -27,104 +27,173 @@ @implementation MPOutlineDataSource - (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pasteboard { - self.draggedGroup = nil; if([items count] == 1) { id item = [[items lastObject] representedObject]; if(![item isKindOfClass:[KPKGroup class]]) { return NO; } - [pasteboard setString:self.draggedGroup.name forType:KPKGroupUTI]; - self.draggedGroup = item; - return (nil != self.draggedGroup.parent); + KPKGroup *draggedGroup = item; + [pasteboard writeObjects:@[draggedGroup]]; + return (nil != draggedGroup.parent); } return NO; } - (NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id)info proposedItem:(id)item proposedChildIndex:(NSInteger)index { + + /* Clean up our local search */ + self.localDraggedEntry = nil; + self.localDraggedGroup = nil; + info.animatesToDestination = YES; - NSDragOperation oprationMask = NSDragOperationMove; + NSDragOperation operationMask = NSDragOperationMove; /* If we can support copy on drag, this can be used to optain the dragging modifier mask the user presses - if([info draggingSourceOperationMask] == NSDragOperationCopy) { - oprationMask = NSDragOperationCopy; - } */ - - NSPasteboard *pasteBoard = [info draggingPasteboard]; - NSArray *types = [pasteBoard types]; - if([types count] > 1 || [types count] == 0) { - return NSDragOperationNone; // We cannot work with more than one type + BOOL localCopy = NO; + if([info draggingSourceOperationMask] == NSDragOperationCopy) { + operationMask = NSDragOperationCopy; + localCopy = YES; } - + + + /* Check if the Target is the root group */ id targetItem = [item representedObject]; - if( ![targetItem isKindOfClass:[KPKGroup class]] && ![targetItem isKindOfClass:[KPKEntry class]]) { + if( ![targetItem isKindOfClass:[KPKGroup class]] ) { return NSDragOperationNone; // Block all unknown types } - MPDocument *document = [[[outlineView window] windowController] document]; - NSString *draggedType = [types lastObject]; - if([draggedType isEqualToString:KPKGroupUTI]) { - // dragging group - self.draggedEntry = nil; - } - else if([draggedType isEqualToString:KPKUUIDUTI]) { - NSArray *uuids = [pasteBoard readObjectsForClasses:@[[NSUUID class]] options:nil]; - if([uuids count] != 1) { - return NSDragOperationNone; // NO entry readable - } - self.draggedGroup = nil; - self.draggedEntry = [document findEntry:[uuids lastObject]]; - } - else { - return NSDragOperationNone; // unkonw type + + NSPasteboard *pasteBoard = [info draggingPasteboard]; + KPKGroup *draggedGroup = nil; + KPKEntry *draggedEntry = nil; + BOOL couldReadPasteboard = [self _readDataFromPasteboard:pasteBoard group:&draggedGroup entry:&draggedEntry]; + if(!couldReadPasteboard) { + return NSDragOperationNone; } KPKGroup *targetGroup = targetItem; BOOL validTarget = YES; - if(self.draggedGroup) { - if( self.draggedGroup == targetGroup ) { + MPDocument *document = [[[outlineView window] windowController] document]; + /* Dragging Groups */ + if(draggedGroup) { + self.localDraggedGroup = [document findGroup:draggedGroup.uuid]; + if( [draggedGroup.uuid isEqual:targetGroup.uuid] ) { return NSDragOperationNone; // Groups cannot be moved inside themselves } - if( self.draggedGroup.parent == targetGroup ) { - validTarget &= index != NSOutlineViewDropOnItemIndex; - validTarget &= index != [self.draggedGroup.parent.groups indexOfObject:self.draggedGroup]; + if(self.localDraggedGroup) { + if( self.localDraggedGroup.parent == targetGroup ) { + validTarget &= index != NSOutlineViewDropOnItemIndex; + validTarget &= index != [self.localDraggedGroup.parent.groups indexOfObject:self.localDraggedGroup]; + } + BOOL isAnchesor = [self.localDraggedGroup isAnchestorOfGroup:targetGroup]; + validTarget &= !isAnchesor; + } + else { + operationMask = NSDragOperationCopy; } - BOOL isAnchesor = [self.draggedGroup isAnchestorOfGroup:targetGroup]; - validTarget &= !isAnchesor; } - else if(self.draggedEntry) { - validTarget = self.draggedEntry.parent != targetGroup; - [outlineView setDropItem:item dropChildIndex:NSOutlineViewDropOnItemIndex]; + else if(draggedEntry) { + self.localDraggedEntry = [document findEntry:draggedEntry.uuid]; + if(self.localDraggedEntry) { + /* local Copy is always valid regardless of parent */ + validTarget = localCopy ? YES : self.localDraggedEntry.parent != targetGroup; + [outlineView setDropItem:item dropChildIndex:NSOutlineViewDropOnItemIndex]; + } + else { + /* Entry copy is always valid */ + operationMask = NSDragOperationCopy; + } } - return validTarget ? oprationMask : NSDragOperationNone; + return validTarget ? operationMask : NSDragOperationNone; } - (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id)info item:(id)item childIndex:(NSInteger)index { info.animatesToDestination = YES; - NSPasteboard *pasteBoard = [info draggingPasteboard]; - NSArray *types = [pasteBoard types]; - if([types count] > 1 || [types count] == 0) { - return NO; // We cannot work with more than one type - } id targetItem = [item representedObject]; if(![targetItem isKindOfClass:[KPKGroup class]]) { return NO; // Wrong } + NSPasteboard *pasteBoard = [info draggingPasteboard]; + KPKGroup *draggedGroup = nil; + KPKEntry *draggedEntry = nil; + BOOL validPateboard = [self _readDataFromPasteboard:pasteBoard group:&draggedGroup entry:&draggedEntry]; + if(!validPateboard) { + return NO; + } + + BOOL copyItem = ([info draggingSourceOperationMask] == NSDragOperationCopy); + KPKGroup *targetGroup = (KPKGroup *)targetItem; + if(draggedGroup) { + if(copyItem || (nil == self.localDraggedGroup) ) { + /* + Scenarios: + a) Local copy + b) Drag from other document + */ + return NO; + } + else if(self.localDraggedGroup) { + /* Simple move */ + [self.localDraggedGroup moveToGroup:targetGroup atIndex:index]; + [self.localDraggedGroup.undoManager setActionName:NSLocalizedString(@"MOVE_GROUP", "")]; + return YES; + } + /* Nothing valid */ + return NO; + } + else if(draggedEntry) { + if(copyItem || (nil == self.localDraggedEntry)) { + /* + Scenarios: + a) Local copy + b) Drag from other document + */ + return NO; + } + else if(self.localDraggedEntry) { + [self.localDraggedEntry moveToGroup:targetGroup atIndex:index]; + [self.localDraggedEntry.undoManager setActionName:NSLocalizedString(@"MOVE_ENTRY", "")]; + return YES; + } + } + return NO; +} + +- (BOOL)_readDataFromPasteboard:(NSPasteboard *)pasteboard group:(KPKGroup **)group entry:(KPKEntry **)entry;{ + + if(entry == NULL || group == NULL) { + return NO; // Need valid pointers + } + /* Cleanup old stuff */ + + NSArray *types = [pasteboard types]; + if([types count] > 1 || [types count] == 0) { + return NO; + } NSString *draggedType = [types lastObject]; if([draggedType isEqualToString:KPKGroupUTI]) { - [self.draggedGroup moveToGroup:targetGroup atIndex:index]; - [self.draggedGroup.undoManager setActionName:NSLocalizedString(@"MOVE_GROUP", "")]; + // dragging group + NSArray *groups = [pasteboard readObjectsForClasses:@[[KPKGroup class]] options:nil]; + if([groups count] != 1) { + return NO; + } + *group = [groups lastObject]; return YES; } - else if([draggedType isEqualToString:KPKUUIDUTI]) { - [self.draggedEntry moveToGroup:targetGroup atIndex:index]; - [self.draggedEntry.undoManager setActionName:NSLocalizedString(@"MOVE_ENTRY", "")]; + else if([draggedType isEqualToString:KPKEntryUTI]) { + NSArray *entries = [pasteboard readObjectsForClasses:@[[KPKEntry class]] options:nil]; + if([entries count] != 1) { + return NO; // NO entry readable + } + *entry = [entries lastObject]; return YES; } return NO; } + @end diff --git a/MacPass/MPOutlineViewController.m b/MacPass/MPOutlineViewController.m index 0dbb0272..0f5e4bad 100644 --- a/MacPass/MPOutlineViewController.m +++ b/MacPass/MPOutlineViewController.m @@ -73,7 +73,7 @@ NSString *const _MPOutlinveViewHeaderViewIdentifier = @"HeaderCell"; [_outlineView setMenu:[self _contextMenu]]; [_outlineView setAllowsEmptySelection:YES]; [_outlineView setFloatsGroupRows:NO]; - [_outlineView registerForDraggedTypes:@[ KPKGroupUTI, KPKUUIDUTI ]]; + [_outlineView registerForDraggedTypes:@[ KPKGroupUTI, KPKEntryUTI ]]; [_outlineView setDraggingSourceOperationMask:NSDragOperationEvery forLocal:YES]; [_bottomBar setBorderType:HNHBorderTop]; [_addGroupButton setAction:[MPActionHelper actionOfType:MPActionAddGroup]];