Какао NSTextField Drag & Drop действительно требует подкласса?

До сегодняшнего дня у меня никогда не было возможности использовать что-либо, кроме самого NSWindow в качестве NSDraggingDestination. При использовании окна в качестве универсального пункта назначения для перетаскивания NSWindow передает эти сообщения своему делегату, позволяя обрабатывать отбрасывание без создания подкласса NSWindow.

Документы скажите:

Хотя NSDraggingDestination объявлен как неформальный протокол, подклассы NSWindow и NSView, которые вы создаете для принятия протокола, должны реализовывать только те методы, которые уместны. (Классы NSWindow и NSView предоставляют частные реализации для всех методов.) Эти методы могут быть реализованы либо оконным объектом, либо его делегатом; однако реализация делегата имеет приоритет, если есть реализации в обоих местах.

Сегодня у меня было окно с двумя NSTextFields на нем, и я хотел, чтобы у них было другое поведение при перетаскивании, и я не хотел допускать перетаскивания где-либо еще в окне. То, как я интерпретирую документы, кажется, что мне нужно либо создать подкласс NSTextField, либо создать несколько гигантских спагетти-условных обработчиков перетаскивания в делегате окна, которые проверяют перетаскивание для каждого представления, чтобы выбрать различные варианты поведения области перетаскивания для каждое поле.

Подход централизованного обработчика перетаскивания на основе делегатов NSWindow кажется обременительным в любом случае, когда у вас было больше, чем небольшая горстка представлений назначения перетаскивания. Точно так же подход к подклассам кажется обременительным независимо от случая, потому что теперь код обработки отбрасывания находится в классе представления, поэтому, как только вы принимаете отбрасывание, вам нужно придумать какой-то способ маршалинга отброшенных данных обратно в модель. docs предупредить вас о попытках управлять привязками, задав значение пользовательского интерфейса программно. Так что теперь вы тоже застряли, пытаясь обойти это.

Итак, мой вопрос: «Правда !? Это единственные доступные варианты? Или мне здесь не хватает чего-то простого?»

Спасибо.


person ipmcc    schedule 08.01.2011    source источник
comment
Вам следует исправить опечатку в заголовке вопроса (NSTextView! = NSTextField).   -  person NSGod    schedule 09.01.2011


Ответы (1)


После небольшого дополнительного исследования выясняется, что «Да, действительно, у вас есть два варианта: либо создать подкласс NSTextField, либо использовать NSWindowDelegate для обработки падений». Я пойду дальше и заявлю, что лучший из двух способов для разнообразных садовых случаев «Я хочу несколько зон перетаскивания в одном окне» - это использовать метод NSWindowDelegate с проверками попадания, поскольку вы избегаете проблемы имея код обработки перетаскивания на стороне просмотра. Я закончил с этим методом draggingUpdated: в моем классе оконного делегата:

- (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)sender
{
    NSPasteboard *pboard = [sender draggingPasteboard];
    NSDragOperation sourceDragMask = [sender draggingSourceOperationMask];

    if ([pboard.types containsObject: NSFilenamesPboardType] && (sourceDragMask & NSDragOperationCopy))
    {
        NSView* hitView = [sender.draggingDestinationWindow.contentView hitTest: sender.draggingLocation];
        if (hitView && (hitView == mSourceTextField || hitView == mDestTextField))
        {
            return NSDragOperationCopy;            
        }
    }

    return NSDragOperationNone;
}

Очевидно, что это не все, но подход, основанный на hitTest:, пока работает для меня. Я подозреваю, что это было бы немного сложнее, если бы кто-то работал с элементом управления на основе нескольких NSCell, таким как NSTableView или NSOutlineView, но неудивительно, что у них есть свои собственные методы обработки перетаскивания.

Надеюсь, это поможет кому-то другому.

person ipmcc    schedule 11.01.2011