Skip to content

Commit

Permalink
Improve drag/drop support
Browse files Browse the repository at this point in the history
Notify delegate on reorder
  • Loading branch information
LeoNatan committed May 5, 2021
1 parent 7c63414 commit 1366ca3
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ typedef struct {
unsigned int delegate_canAddNewNodeInNode : 1;
unsigned int delegate_canMoveNode : 1;
unsigned int delegate_canPasteNode : 1;
unsigned int delegate_canReorderChildrenOfNode : 1;
unsigned int delegate_defaultPropertyListForAddingInNode : 1;

unsigned int dataTransformer_displayNameForNode : 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ - (void)setDelegate:(id<LNPropertyListEditorDelegate>)delegate
_flags.delegate_canPasteNode = [delegate respondsToSelector:@selector(propertyListEditor:canPasteNode:asChildOfNode:)];
_flags.delegate_defaultPropertyListForAddingInNode = [delegate respondsToSelector:@selector(propertyListEditor:defaultPropertyListForChildInNode:)];
_flags.delegate_canMoveNode = [delegate respondsToSelector:@selector(propertyListEditor:canMoveNode:toParentNode:atIndex:)];
_flags.delegate_canReorderChildrenOfNode = [delegate respondsToSelector:@selector(propertyListEditor:canReorderChildrenOfNode:)];
}

- (void)setDataTransformer:(id<LNPropertyListEditorDataTransformer>)dataTransformer
Expand All @@ -143,7 +144,7 @@ - (void)setDataTransformer:(id<LNPropertyListEditorDataTransformer>)dataTransfor
- (void)setPropertyListObject:(id)propertyList
{
_rootPropertyListNode = [[LNPropertyListNode alloc] initWithPropertyListObject:propertyList];
[_rootPropertyListNode _sortUsingDescriptors:_outlineView.sortDescriptors];
[self _sortRootNodeIfPossibleWithSortDescriptors:_outlineView.sortDescriptors];

[_outlineView reloadData];

Expand Down Expand Up @@ -325,7 +326,7 @@ - (void)_updateValue:(id)value ofNode:(LNPropertyListNode*)node reloadItem:(BOOL
}
}

- (void)_insertNode:(LNPropertyListNode*)insertedNode inParentNode:(LNPropertyListNode*)parentNode index:(NSInteger)insertionIndex groupUndoOperation:(BOOL)groupUndo
- (void)_insertNode:(LNPropertyListNode*)insertedNode inParentNode:(LNPropertyListNode*)parentNode index:(NSInteger)insertionIndex notifyDelegate:(BOOL)notifyDelegate groupUndoOperation:(BOOL)groupUndo
{
insertedNode.parent = parentNode;

Expand Down Expand Up @@ -356,7 +357,7 @@ - (void)_insertNode:(LNPropertyListNode*)insertedNode inParentNode:(LNPropertyLi
[parentNode.children insertObject:insertedNode atIndex:insertionIndex];
[_outlineView insertItemsAtIndexes:[NSIndexSet indexSetWithIndex:insertionIndex] inParent:parentNodeInOutline withAnimation:NSTableViewAnimationEffectNone];

if(_flags.delegate_willChangeNode)
if(notifyDelegate && _flags.delegate_willChangeNode)
{
[self.delegate propertyListEditor:self willChangeNode:insertedNode changeType:LNPropertyListNodeChangeTypeInsert previousKey:nil];
}
Expand All @@ -380,14 +381,14 @@ - (void)_insertNode:(LNPropertyListNode*)insertedNode inParentNode:(LNPropertyLi
[_undoManager beginUndoGrouping];
}
[_undoManager registerUndoWithTarget:self handler:^(LNPropertyListEditor* _Nonnull target) {
[target _deleteNode:insertedNode groupUndoOperation:groupUndo];
[target _deleteNode:insertedNode notifyDelegate:notifyDelegate groupUndoOperation:groupUndo];
}];
if(groupUndo)
{
[_undoManager endUndoGrouping];
}

if(_flags.delegate_didChangeNode)
if(notifyDelegate && _flags.delegate_didChangeNode)
{
[self.delegate propertyListEditor:self didChangeNode:insertedNode changeType:LNPropertyListNodeChangeTypeInsert previousKey:nil];
}
Expand Down Expand Up @@ -419,10 +420,10 @@ - (void)_insertNode:(LNPropertyListNode*)insertedNode sender:(id)sender
insertionRow = [parentNode.children indexOfObject:node] + 1;
}

[self _insertNode:insertedNode inParentNode:parentNode index:insertionRow groupUndoOperation:YES];
[self _insertNode:insertedNode inParentNode:parentNode index:insertionRow notifyDelegate:YES groupUndoOperation:YES];
}

- (void)_deleteNode:(LNPropertyListNode*)deletedNode groupUndoOperation:(BOOL)groupUndo
- (void)_deleteNode:(LNPropertyListNode*)deletedNode notifyDelegate:(BOOL)notifyDelegate groupUndoOperation:(BOOL)groupUndo
{
if(deletedNode.parent == nil)
{
Expand All @@ -440,7 +441,7 @@ - (void)_deleteNode:(LNPropertyListNode*)deletedNode groupUndoOperation:(BOOL)gr

[_outlineView beginUpdates];

if(_flags.delegate_willChangeNode)
if(notifyDelegate && _flags.delegate_willChangeNode)
{
[self.delegate propertyListEditor:self willChangeNode:deletedNode changeType:LNPropertyListNodeChangeTypeDelete previousKey:deletedNode.key];
}
Expand Down Expand Up @@ -472,7 +473,7 @@ - (void)_deleteNode:(LNPropertyListNode*)deletedNode groupUndoOperation:(BOOL)gr
[_undoManager beginUndoGrouping];
}
[_undoManager registerUndoWithTarget:self handler:^(LNPropertyListEditor* _Nonnull target) {
[target _insertNode:deletedNode inParentNode:parentNode index:deletionIndex groupUndoOperation:groupUndo];
[target _insertNode:deletedNode inParentNode:parentNode index:deletionIndex notifyDelegate:notifyDelegate groupUndoOperation:groupUndo];
}];
if(groupUndo)
{
Expand All @@ -488,7 +489,7 @@ - (void)_deleteNode:(LNPropertyListNode*)deletedNode groupUndoOperation:(BOOL)gr
[_outlineView selectRowIndexes:[NSIndexSet indexSetWithIndex:selectedRow] byExtendingSelection:NO];
}

if(_flags.delegate_didChangeNode)
if(notifyDelegate && _flags.delegate_didChangeNode)
{
[self.delegate propertyListEditor:self didChangeNode:deletedNode changeType:LNPropertyListNodeChangeTypeDelete previousKey:deletedNode.key];
}
Expand All @@ -509,15 +510,33 @@ - (void)_deleteNodeWithSender:(id)sender

LNPropertyListNode* deletedNode = [_outlineView itemAtRow:row];

[self _deleteNode:deletedNode groupUndoOperation:YES];
[self _deleteNode:deletedNode notifyDelegate:YES groupUndoOperation:YES];
}

- (void)_moveNode:(LNPropertyListNode*)node intoParentNode:(LNPropertyListNode*)parentNode index:(NSInteger)parentIndex
{
if(_flags.delegate_willChangeNode)
{
[self.delegate propertyListEditor:self willChangeNode:node changeType:LNPropertyListNodeChangeTypeMove previousKey:nil];
}
[_undoManager beginUndoGrouping];
[self _deleteNode:node groupUndoOperation:NO];
[self _insertNode:node inParentNode:parentNode index:parentIndex groupUndoOperation:NO];
NSInteger indexDelta = 0;
if(node.parent == parentNode)
{
NSInteger beforeIndex = [node.parent.children indexOfObject:node];
if(beforeIndex < parentIndex)
{
indexDelta = -1;
}
}
parentIndex += indexDelta;
[self _deleteNode:node notifyDelegate:NO groupUndoOperation:NO];
[self _insertNode:node inParentNode:parentNode index:parentIndex notifyDelegate:NO groupUndoOperation:NO];
[_undoManager endUndoGrouping];
if(_flags.delegate_didChangeNode)
{
[self.delegate propertyListEditor:self didChangeNode:node changeType:LNPropertyListNodeChangeTypeMove previousKey:nil];
}
}

#pragma mark Private
Expand Down Expand Up @@ -1086,13 +1105,35 @@ - (void)outlineViewItemDidCollapse:(NSNotification *)notification
[[self.outlineView rowViewAtRow:[self.outlineView rowForItem:item] makeIfNecessary:NO] updateEditButtons];
}

- (void)_sortRootNodeIfPossibleWithSortDescriptors:(NSArray<NSSortDescriptor *> *)sortDescriptors
{
[self.rootPropertyListNode _sortUsingDescriptors:sortDescriptors validator:^BOOL(LNPropertyListNode* node) {
if(!_flags.delegate_canReorderChildrenOfNode)
{
return YES;
}

return [self.delegate propertyListEditor:self canReorderChildrenOfNode:node];
} callback:^(LNPropertyListNode* node, BOOL will) {
if(will && _flags.delegate_willChangeNode)
{
[self.delegate propertyListEditor:self willChangeNode:node changeType:LNPropertyListNodeChangeTypeReorderChildren previousKey:nil];
}

if(!will && _flags.delegate_didChangeNode)
{
[self.delegate propertyListEditor:self didChangeNode:node changeType:LNPropertyListNodeChangeTypeReorderChildren previousKey:nil];
}
}];
}

- (void)outlineView:(NSOutlineView *)outlineView sortDescriptorsDidChange:(NSArray<NSSortDescriptor *> *)oldDescriptors;
{
//Make the outline view as the first responder to prevent issues with currently edited text fields.
[outlineView.window makeFirstResponder:outlineView];

LNPropertyListNode* node = [outlineView itemAtRow:outlineView.selectedRow];
[self.rootPropertyListNode _sortUsingDescriptors:outlineView.sortDescriptors];
[self _sortRootNodeIfPossibleWithSortDescriptors:outlineView.sortDescriptors];
[self.outlineView reloadItem:nil reloadChildren:YES];

NSInteger selectionRow = [self.outlineView rowForItem:node];
Expand Down Expand Up @@ -1158,7 +1199,7 @@ - (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id<NSDraggingInfo>)

if(info.draggingSourceOperationMask == NSDragOperationCopy)
{
[self _insertNode:draggedItem.copy inParentNode:item index:index groupUndoOperation:YES];
[self _insertNode:draggedItem.copy inParentNode:item index:index notifyDelegate:YES groupUndoOperation:YES];
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ extern NSString* const LNPropertyListNodeXcodeKeyType;

- (void)_setObject:(id)object;

- (void)_sortUsingDescriptors:(NSArray<NSSortDescriptor *> *)descriptors;
- (void)_sortUsingDescriptors:(NSArray<NSSortDescriptor *> *)descriptors validator:(BOOL (^)(LNPropertyListNode*))validator callback:(void (^)(LNPropertyListNode*, BOOL))callback;

- (id<NSPasteboardWriting>)pasteboardWriter;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -414,18 +414,25 @@ - (LNPropertyListNode*)childNodeForKey:(NSString*)key
return [self.children filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"key == %@", key]].firstObject;
}

- (void)_sortUsingDescriptors:(NSArray<NSSortDescriptor *> *)descriptors
- (void)_sortUsingDescriptors:(NSArray<NSSortDescriptor *> *)descriptors validator:(BOOL (^)(LNPropertyListNode*))validator callback:(void (^)(LNPropertyListNode*, BOOL))callback
{
if(self.type != LNPropertyListNodeTypeDictionary && self.type != LNPropertyListNodeTypeArray)
{
return;
}

if(validator(self) == NO)
{
return;
}

callback(self, YES);
[self.children sortUsingDescriptors:descriptors];

[self.children enumerateObjectsUsingBlock:^(LNPropertyListNode * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[obj _sortUsingDescriptors:descriptors];
[obj _sortUsingDescriptors:descriptors validator:validator callback:callback];
}];
callback(self, NO);
}

- (id)pasteboardWriter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ typedef NS_ENUM(NSUInteger, LNPropertyListNodeChangeType) {
LNPropertyListNodeChangeTypeInsert,
LNPropertyListNodeChangeTypeDelete,
LNPropertyListNodeChangeTypeMove,
LNPropertyListNodeChangeTypeUpdate
LNPropertyListNodeChangeTypeUpdate,
LNPropertyListNodeChangeTypeReorderChildren,
};

NS_ASSUME_NONNULL_BEGIN
Expand Down Expand Up @@ -53,10 +54,14 @@ NS_ASSUME_NONNULL_BEGIN
/// @param editor The property list editor.
/// @param node The current node.
- (BOOL)propertyListEditor:(LNPropertyListEditor *)editor canDeleteNode:(LNPropertyListNode*)node;
/// Asks the delegate if it is possible add a child node in the specified node.
/// Asks the delegate if it is possible to add a child node in the specified node.
/// @param editor The property list editor.
/// @param node The current node.
- (BOOL)propertyListEditor:(LNPropertyListEditor *)editor canAddChildNodeInNode:(LNPropertyListNode*)node;
/// Asks the delegate if it is possible to reorder the children of the specified node.
/// @param editor The property list editor.
/// @param node The current node.
- (BOOL)propertyListEditor:(LNPropertyListEditor *)editor canReorderChildrenOfNode:(LNPropertyListNode*)node;
/// Asks the delegate if the specified pasted node can be added as a child node of the specified node.
/// @param editor The property list editor.
/// @param pastedNode The pasted node.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,21 @@ - (void)propertyListEditor:(LNPropertyListEditor *)editor willChangeNode:(LNProp
switch(changeType)
{
case LNPropertyListNodeChangeTypeMove:
NSLog(@"➡️");
NSLog(@"➡️ Moved %@", node);
break;
case LNPropertyListNodeChangeTypeInsert:
NSLog(@"🎉");
NSLog(@"🎉 Inserted %@", node);
break;
case LNPropertyListNodeChangeTypeDelete:
NSLog(@"🗑");
NSLog(@"🗑 Deleted %@", node);
break;
case LNPropertyListNodeChangeTypeUpdate:
NSLog(@"🔄");
NSLog(@"🔄 Updated %@", node);
break;
case LNPropertyListNodeChangeTypeReorderChildren:
NSLog(@"📚 Children Reordered %@", node);
break;
}

NSLog(@"%@", [editor.rootPropertyListNode childNodeContainingDescendantNode:node]);
}

@end

0 comments on commit 1366ca3

Please sign in to comment.