mirror of
https://github.com/MacPass/MacPass.git
synced 2025-12-14 12:52:21 +00:00
Changed drag and drop architecture to use pasteboard and encoded entries/groups
First steps to enhance drag and drop to for cross document dragging and inter-document copying
This commit is contained in:
@@ -50,7 +50,6 @@
|
||||
<int key="NSvFlags">268</int>
|
||||
<string key="NSFrame">{{57, 409}, {204, 17}}</string>
|
||||
<reference key="NSSuperview" ref="233312071"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="45251842"/>
|
||||
<string key="NSReuseIdentifierKey">_NS:1535</string>
|
||||
<string key="NSAntiCompressionPriority">{249, 750}</string>
|
||||
@@ -100,7 +99,6 @@
|
||||
</set>
|
||||
<string key="NSFrame">{{20, 401}, {32, 32}}</string>
|
||||
<reference key="NSSuperview" ref="233312071"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="990836775"/>
|
||||
<string key="NSReuseIdentifierKey">_NS:9</string>
|
||||
<bool key="NSEnabled">YES</bool>
|
||||
@@ -126,10 +124,10 @@
|
||||
<array class="NSMutableArray" key="NSSubviews">
|
||||
<object class="NSButton" id="830540359">
|
||||
<reference key="NSNextResponder" ref="381395509"/>
|
||||
<int key="NSvFlags">-2147483380</int>
|
||||
<string key="NSFrame">{{20, 2}, {172, 25}}</string>
|
||||
<int key="NSvFlags">268</int>
|
||||
<string key="NSFrame">{{20, 2}, {42, 25}}</string>
|
||||
<reference key="NSSuperview" ref="381395509"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView"/>
|
||||
<string key="NSReuseIdentifierKey">_NS:22</string>
|
||||
<bool key="NSEnabled">YES</bool>
|
||||
<object class="NSButtonCell" key="NSCell" id="348505851">
|
||||
@@ -139,12 +137,8 @@
|
||||
<reference key="NSSupport" ref="240853158"/>
|
||||
<string key="NSCellIdentifier">_NS:22</string>
|
||||
<reference key="NSControlView" ref="830540359"/>
|
||||
<int key="NSButtonFlags">918306816</int>
|
||||
<int key="NSButtonFlags">-2034483200</int>
|
||||
<int key="NSButtonFlags2">163</int>
|
||||
<object class="NSCustomResource" key="NSNormalImage">
|
||||
<string key="NSClassName">NSImage</string>
|
||||
<string key="NSResourceName">07_NotepadTemplate</string>
|
||||
</object>
|
||||
<string key="NSAlternateContents"/>
|
||||
<string key="NSKeyEquivalent"/>
|
||||
<int key="NSPeriodicDelay">400</int>
|
||||
@@ -155,7 +149,6 @@
|
||||
</array>
|
||||
<string key="NSFrameSize">{278, 30}</string>
|
||||
<reference key="NSSuperview" ref="233312071"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="830540359"/>
|
||||
<string key="NSReuseIdentifierKey">_NS:9</string>
|
||||
<string key="NSClassName">HNHGradientView</string>
|
||||
@@ -165,7 +158,7 @@
|
||||
<int key="NSvFlags">12</int>
|
||||
<string key="NSFrame">{{0, 30}, {278, 369}}</string>
|
||||
<reference key="NSSuperview" ref="233312071"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="906788312"/>
|
||||
<string key="NSReuseIdentifierKey">_NS:9</string>
|
||||
<array class="NSMutableArray" key="NSTabViewItems">
|
||||
<object class="NSTabViewItem" id="367063082">
|
||||
@@ -175,7 +168,7 @@
|
||||
<int key="NSvFlags">256</int>
|
||||
<string key="NSFrameSize">{278, 369}</string>
|
||||
<reference key="NSSuperview" ref="45251842"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="381395509"/>
|
||||
<string key="NSReuseIdentifierKey">_NS:28</string>
|
||||
</object>
|
||||
<string key="NSLabel">Entry</string>
|
||||
@@ -253,7 +246,6 @@
|
||||
</array>
|
||||
<string key="NSFrameSize">{278, 443}</string>
|
||||
<reference key="NSSuperview"/>
|
||||
<reference key="NSWindow"/>
|
||||
<reference key="NSNextKeyView" ref="621131831"/>
|
||||
<string key="NSReuseIdentifierKey">_NS:9</string>
|
||||
<string key="NSClassName">NSView</string>
|
||||
@@ -956,110 +948,17 @@
|
||||
<nil key="activeLocalization"/>
|
||||
<dictionary class="NSMutableDictionary" key="localizations"/>
|
||||
<nil key="sourceID"/>
|
||||
<int key="maxID">3116</int>
|
||||
</object>
|
||||
<object class="IBClassDescriber" key="IBDocument.Classes">
|
||||
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">HNHGradientView</string>
|
||||
<string key="superclassName">NSView</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBProjectSource</string>
|
||||
<string key="minorKey">./Classes/HNHGradientView.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">MPInspectorViewController</string>
|
||||
<string key="superclassName">MPViewController</string>
|
||||
<object class="NSMutableDictionary" key="actions">
|
||||
<string key="NS.key.0">showImagePopup:</string>
|
||||
<string key="NS.object.0">id</string>
|
||||
</object>
|
||||
<object class="NSMutableDictionary" key="actionInfosByName">
|
||||
<string key="NS.key.0">showImagePopup:</string>
|
||||
<object class="IBActionInfo" key="NS.object.0">
|
||||
<string key="name">showImagePopup:</string>
|
||||
<string key="candidateClassName">id</string>
|
||||
</object>
|
||||
</object>
|
||||
<dictionary class="NSMutableDictionary" key="outlets">
|
||||
<string key="bottomBar">HNHGradientView</string>
|
||||
<string key="createdTextField">NSTextField</string>
|
||||
<string key="itemImageView">MPPopupImageView</string>
|
||||
<string key="itemNameTextField">NSTextField</string>
|
||||
<string key="modifiedTextField">NSTextField</string>
|
||||
<string key="noSelectionInfo">NSTextField</string>
|
||||
<string key="tabView">NSTabView</string>
|
||||
</dictionary>
|
||||
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
|
||||
<object class="IBToOneOutletInfo" key="bottomBar">
|
||||
<string key="name">bottomBar</string>
|
||||
<string key="candidateClassName">HNHGradientView</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo" key="createdTextField">
|
||||
<string key="name">createdTextField</string>
|
||||
<string key="candidateClassName">NSTextField</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo" key="itemImageView">
|
||||
<string key="name">itemImageView</string>
|
||||
<string key="candidateClassName">MPPopupImageView</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo" key="itemNameTextField">
|
||||
<string key="name">itemNameTextField</string>
|
||||
<string key="candidateClassName">NSTextField</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo" key="modifiedTextField">
|
||||
<string key="name">modifiedTextField</string>
|
||||
<string key="candidateClassName">NSTextField</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo" key="noSelectionInfo">
|
||||
<string key="name">noSelectionInfo</string>
|
||||
<string key="candidateClassName">NSTextField</string>
|
||||
</object>
|
||||
<object class="IBToOneOutletInfo" key="tabView">
|
||||
<string key="name">tabView</string>
|
||||
<string key="candidateClassName">NSTabView</string>
|
||||
</object>
|
||||
</dictionary>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBProjectSource</string>
|
||||
<string key="minorKey">./Classes/MPInspectorViewController.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">MPPopupImageView</string>
|
||||
<string key="superclassName">NSImageView</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBProjectSource</string>
|
||||
<string key="minorKey">./Classes/MPPopupImageView.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">MPViewController</string>
|
||||
<string key="superclassName">NSViewController</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBProjectSource</string>
|
||||
<string key="minorKey">./Classes/MPViewController.h</string>
|
||||
</object>
|
||||
</object>
|
||||
<object class="IBPartialClassDescription">
|
||||
<string key="className">NSLayoutConstraint</string>
|
||||
<string key="superclassName">NSObject</string>
|
||||
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||
<string key="majorKey">IBProjectSource</string>
|
||||
<string key="minorKey">./Classes/NSLayoutConstraint.h</string>
|
||||
</object>
|
||||
</object>
|
||||
</array>
|
||||
<int key="maxID">3117</int>
|
||||
</object>
|
||||
<object class="IBClassDescriber" key="IBDocument.Classes"/>
|
||||
<int key="IBDocument.localizationMode">0</int>
|
||||
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
|
||||
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
|
||||
<int key="IBDocument.defaultPropertyAccessControl">3</int>
|
||||
<dictionary class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes">
|
||||
<string key="07_NotepadTemplate">{128, 128}</string>
|
||||
<string key="NSActionTemplate">{15, 15}</string>
|
||||
</dictionary>
|
||||
<object class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes">
|
||||
<string key="NS.key.0">NSActionTemplate</string>
|
||||
<string key="NS.object.0">{15, 15}</string>
|
||||
</object>
|
||||
<bool key="IBDocument.UseAutolayout">YES</bool>
|
||||
</data>
|
||||
</archive>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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<NSDraggingInfo>)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<NSDraggingInfo>)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
|
||||
|
||||
@@ -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]];
|
||||
|
||||
Reference in New Issue
Block a user