Как использовать NSStatusItem в качестве места назначения перетаскивания?
Я пытаюсь создать приложение, которое позволяет пользователям перетаскивать файлы из Finder в значок меню для обработки. Я добился прогресса в своем путешествии, но, похоже, я не могу подняться на этот холм. Я попытался подклассифицировать NSView и реализовать сообщения перетаскивания.
@interface CMDroppableView : NSView <NSMenuDelegate>
Я хотел не только принимать операции перетаскивания, но и предоставлять NSMenu, когда пользователь нажимает значок. Мне удалось отобразить NSMenu правильно, но функция перетаскивания остается неуловимой.
Я понимаю, что мне нужно было зарегистрировать принятые типы перетаскивания, которые я сделал здесь:
-(void)awakeFromNib{
[self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
}
Перетащите сообщения:
-(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender{
NSLog(@"Drag Enter");
return NSDragOperationCopy;
}
-(NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender{
return NSDragOperationCopy;
}
-(void)draggingExited:(id <NSDraggingInfo>)sender{
NSLog(@"Drag Exit");
}
-(BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender{
return YES;
}
-(BOOL)performDragOperation:(id <NSDraggingInfo>)sender{
return YES;
}
Вот код, в котором установлен пользовательский вид:
statusItemView = [[CMDroppableView alloc] init];
[statusItemView retain];
[statusItemView setMenu: statusMenu];
[statusItem setView: statusItemView];
По-прежнему ничего. Итак, где я ошибся?
Спасибо!
Ответы
Ответ 1
Изменить: D'oh, вы регистрируете типы перетаскивания в -awakeFromNib
, которые не будут вызываться, если представление не загружается из ниба. Попробуйте зарегистрировать свои типы перетаскивания в -initWithFrame:
вместо этого!
Старый ответ:
IIRC вам не нужно настраивать меню в элементе статуса. Что я делаю, так это то, что мой пользовательский вид управляет меню и делает что-то вроде этого:
- (void)setMenu:(NSMenu *)menu {
[menu setDelegate:self];
[super setMenu:menu];
}
- (void)mouseDown:(NSEvent *)event {
[statusItem popUpStatusItemMenu:[self menu]]; // or another method that returns a menu
}
- (void)menuWillOpen:(NSMenu *)menu {
highlight = YES;
[self setNeedsDisplay:YES];
}
- (void)menuDidClose:(NSMenu *)menu {
highlight = NO;
[self setNeedsDisplay:YES];
}
- (void)drawRect:(NSRect)rect {
NSImage *img = highlight ? [alternateImage copy] : [image copy];
NSRect bounds = [self bounds];
[statusItem drawStatusBarBackgroundInRect:bounds withHighlight:highlight];
// rest of drawing code goes here, including drawing img where appropriate
}
в моей реализации пользовательского представления. Это гарантирует, что поведение меню идентично по умолчанию.
Ответ 2
Сквозь проб и ошибок я наткнулся на решение. Я регистрировал допустимые типы перетаскивания в сообщении awakeFromNib (как видно из исходного вопроса). Однако я не использовал IB для установки этого вида, поэтому этот метод никогда не вызывался. Перемещение регистрационного кода в сообщение initFromFrame, похоже, устранило проблему.
- (id)initWithFrame:(NSRect)frame {
self = [super initWithFrame:frame];
if (self) {
...
[self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
}
return self;
}