Вы знаете этот эффект, когда вы перетаскиваете элемент из док-станции и появляется курсор облачного перетаскивания, и когда вы отпускаете его, он исчезает с эффектом пуфа? Аналогично, в Xcode, когда вы перетаскиваете точку останова за пределы канального номера, происходит то же самое.
Я хотел бы реализовать тот же эффект в моем приложении, но не могу найти правильный путь.
У меня есть потомок NSImageView для реализации протоколов NSDraggingSource и NSDraggingDestination. У меня есть несколько примеров этого представления, которые позволяют перетаскивать их содержимое между остальными (операция копирования выполняется в этом сценарии, но это имеет смысл только для того, чтобы показать, что у меня есть drag'n drop, имплантированный и полностью работающий для стандартных задач).
Теперь, когда я перетаскиваю изображение из его вида в любом месте (кроме другого экземпляра представления), я хочу, чтобы операция удаления выполнялась при удалении. Однако операция перетаскивания полностью контролируется целевым представлением. Я мог бы заставить их реагировать так, как я хочу (хотя это будет очень много работы), но он полностью не работает, если я перетаскиваю приложение.
Если бы я мог получить операцию перетаскивания delete, я мог бы легко справиться с этим:
- (void)draggedImage: (NSImage *)image
endedAt: (NSPoint)screenPoint
operation: (NSDragOperation)operation
{
if (operation == NSDragOperationDelete) {
NSRect rect = [self.window convertRectToScreen: [self convertRect: self.frame fromView: nil]];
NSShowAnimationEffect(NSAnimationEffectPoof, rect.origin, self.bounds.size, nil, nil, NULL);
}
}
Я уже пытался установить курсор удаления следующим образом:
- (void)draggingSession: (NSDraggingSession *)session
movedToPoint: (NSPoint)screenPoint
{
if (!NSPointInRect(screenPoint, self.window.frame)) {
[[NSCursor disappearingItemCursor] set];
}
}
(для простоты это для всего ветра в данный момент). Это работает до тех пор, пока я не попаду на рабочий стол или окно поиска. В начале мерцает, вероятно, потому, что Finder одновременно устанавливает свой собственный указатель перетаскивания. Это абсолютно без эффекта, когда я попадал в док. Это также происходит, когда я определяю свой собственный тип данных картона.
Кроме того, любое другое представление с включенной возможностью переадресации в моем приложении по-прежнему будет принимать мои данные перетаскивания (например, NSTextView), которые я не хочу выполнять (я пишу NSURL для перетаскивания картона с пользовательской схемой).
Update:
Я сделал еще несколько шагов. Как уже указывал Питер, важно обрабатывать draggingSession:sourceOperationmaskForDraggingContext:
, который выглядит так в моем коде:
- (NSDragOperation) draggingSession: (NSDraggingSession *)session
sourceOperationMaskForDraggingContext: (NSDraggingContext)context;
{
switch(context) {
case NSDraggingContextOutsideApplication:
return NSDragOperationDelete;
break;
case NSDraggingContextWithinApplication:
default:
return NSDragOperationDelete | NSDragOperationMove;
break;
}
}
Это решает 2 проблемы: 1) вне приложения операция перетаскивания вообще не принимается, 2) она не позволяет всем стандартным представлениям принимать эту операцию (потому что NSOutlineView, NSTextView и т.д. не обрабатывают данные операции перетаскивания), Кроме того, я создал собственный тип данных в виде картона, но это не кажется необходимым. Тем не менее, яснее иметь собственный.
К сожалению, отказ от моего потомка NSImageView (как внутри, так и вне приложения) не дает мне NSDragOperationDelete в draggedImage:endedAt:operation:
(что я указал выше), но NSDragOperationNone. Кроме того, курсор перетаскивания при перемещении мыши вне приложения является недопустимым, а не исчезающим элементом. Итак, если кто-то может решить эти две вещи, я бы принял это как ответ на мой вопрос.