0

我正在尝试在表格视图中创建自定义弹出菜单。据我了解,我应该可以通过调用自定义视图中传递的 [NSPopupButtonCell setView:myView] 方法来做到这一点(这只是一个带有 NSOutlineView 的 NSView)。

所以我创建了一个 NSPopupButtonCell 子类,在初始化期间我调用 setView 并传入自定义大纲视图..

编辑

在 IB 中,我将表格列单元格设置为弹出按钮单元格,并将类设置为我的自定义 LookupPopupButtonCell。

我仍然没有显示我的自定义视图,但我的自定义类初始化方法似乎被调用了。

我已经用 NSTableViewDelegate 方法 dataCellForTableColumn 替换了这种方法。现在弹出窗口显示了我的自定义 tableView。

尽管如此,调用 NSOutlineViewDelegate 方法仍然没有乐趣。

编辑好的我已经设法在视图上使用 NSPopupButton 使事情正常进行。委托工作查找和表格视图显示的东西很好。似乎使用 NSPopupButtonCell 委托方法永远不会被调用。

@implementation LookupPopupButtonCell

- (id)init
{
    LOG(@"init called");
    self = [super init];
    if (self) {
        [self initialise];
    }
    return self;
}
- (void)initialise
{
    LOG(@"initialise called");
    
    [self setFont:[NSFont fontWithName:@"System Regular" size:11]];
    [self setBordered:NO];
    [self setBezeled:NO];
    
    // Set the Task Lookup Popup Menu
    NSMenu *newLookupMenu = [[NSMenu allocWithZone:[NSMenu menuZone]] initWithTitle:@"Custom"];
    
    NSMenuItem *newItem = [[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:@"Lookup" action:nil keyEquivalent:@""];
    [newItem setEnabled:YES];
    
    TaskLookupViewController *viewController = [[TaskLookupViewController alloc] initWithNibName:@"TaskLookupViewController" bundle:nil];
    
    [newItem setView:[viewController view]];
    
    [newLookupMenu addItem:newItem];
    [newItem release];
    
    [self setMenu:newLookupMenu];
}
@end

@implementation TaskLookupViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Initialization code here.
        [self initialise];
    }
    
    return self;
}
- (void)awakeFromNib{
    LOG(@"awakeFromNib called...");
    [self viewDidLoad];
}

- (void)viewDidLoad {
    FLOG(@"viewDidLoad called for %@", self);
    /*
    FLOG(@" _outlineView is %@", _outlineView);
    FLOG(@" _outlineView is %@", [_outlineView identifier]);
    FLOG(@" _outlineView delegate is %@", [_outlineView delegate]);
    FLOG(@" _outlineView dataSource is %@", [_outlineView dataSource]);
     */
    [_outlineView setDataSource:self];
    [_outlineView setDelegate:self];
    [_outlineView reloadData];
    [_outlineView selectRowIndexes:[NSIndexSet indexSetWithIndex:0] byExtendingSelection:NO];
    [_outlineView setNeedsDisplay];
    [_outlineView selectRowIndexes:[NSIndexSet indexSetWithIndex:2] byExtendingSelection:NO];
    /*
    FLOG(@" _outlineView delegate is %@", [_outlineView delegate]);
    FLOG(@" _outlineView dataSource is %@", [_outlineView dataSource]);
    */
    //NSTableColumn *tableColumn = [[_outlineView tableColumns] objectAtIndex:0];
    
    //LOG(@" setting bindings");
    
    //[tableColumn bind: @"value" toObject: _treeController withKeyPath: @"arrangedObjects.displayName" options: nil];

}
- (void)initialise {
    LOG(@"initialise called");
    
    _topLevelItems = [[NSArray arrayWithObjects:@"Project", @"Tasks and Deliverables", @"Finance", nil] retain];
    
    _childrenDictionary = [NSMutableDictionary new];
    
    [_childrenDictionary setObject:[NSArray arrayWithObjects:@"Scope", nil] forKey:@"Project"];
    
    //[_childrenDictionary setObject:[NSArray arrayWithObjects:@"Issues", @"Risks", nil] forKey:@"Quality"];

    [_childrenDictionary setObject:[NSArray arrayWithObjects:@"WBS", @"Functions", nil] forKey:@"Tasks and Deliverables"];
    
    [_childrenDictionary setObject:[NSArray arrayWithObjects:@"Expenses", @"Ongoing Costs", @"Timesheets", nil] forKey:@"Finance"];
    
    //[_childrenDictionary setObject:[NSArray arrayWithObjects:@"Applications", @"Interfaces", nil] forKey:@"IT Systems"];
    
    //[_childrenDictionary setObject:[NSArray arrayWithObjects:@"People", @"Setup", nil] forKey:@"Administration"];
    
}

- (NSArray *)_childrenForItem:(id)item {
    LOG(@"_childrenForItem called");
    NSArray *children;
    if (item == nil) {
        children = _topLevelItems;
    } else {
        children = [_childrenDictionary objectForKey:item];
    }
    //FLOG(@" children are %@", children);
    
    return children;
}
@end

@implementation TaskLookupViewController (NSOutlineViewDataSource)

- (void)outlineViewSelectionDidChange:(NSNotification *)notification {
    LOG(@"outlineViewSelectionDidChange: called");
    if ([_outlineView selectedRow] != -1) {
        NSObject *item = [_outlineView itemAtRow:[_outlineView selectedRow]];
        if ([_outlineView parentForItem:item] != nil) {
            // Only change things for non-root items (root items can be selected, but are ignored)
            FLOG(@" selected item is %@", item);
        }
    }
}
- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item {
    FLOG(@"outlineView:child:ofItem: called for item %@", item);
    return [[self _childrenForItem:item] objectAtIndex:index];
}

- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item {
    LOG(@"outlineView:isItemExpandable: called");
    if ([outlineView parentForItem:item] == nil) {
        return YES;
    } else {
        return YES;
    }
}

- (NSInteger) outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
    LOG(@"outlineView:numberOfChildrenOfItem: called");
    FLOG(@" children count is %d", [[self _childrenForItem:item] count]);
    return [[self _childrenForItem:item] count];
}
@end

@implementation TaskLookupViewController (NSOutlineViewDelegate)

- (BOOL)outlineView:(NSOutlineView *)outlineView isGroupItem:(id)item {
    LOG(@"outlineView:isGroupItem: called");
    return [_topLevelItems containsObject:item];
}

- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
{
    LOG(@"willDisplayCell called");
    [cell setTitle:@"Cell Title"];
}

- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item {
    LOG(@"outlineView:viewForTableColumn called");
    // We just return a regular text view.

    if ([_topLevelItems containsObject:item]) {
        NSTextField *result = [outlineView makeViewWithIdentifier:@"HeaderTextField" owner:self];
        // Uppercase the string value, but don't set anything else. NSOutlineView automatically applies attributes as necessary
        NSString *value = [item uppercaseString];
        [result setStringValue:value];
        return result;
    } else  {

        NSTextField *result = [outlineView makeViewWithIdentifier:@"ItemTextField" owner:self];
        [result setStringValue:value];
        return result;
    }
}

- (BOOL)outlineView:(NSOutlineView *)outlineView shouldExpandItem:(id)item;
{
    LOG(@"outlineView:shouldExpandItem: called");
        return YES;
}
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldSelectItem:(id)item;
{
    LOG(@"outlineView:shouldSelectItem: called");
    return YES;
}
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldCollapseItem:(id)item;
{
    LOG(@"outlineView:shouldCollapseItem: called");
    return NO;
}
@end

@implementation TaskLookupViewController (NSTableViewDelegate)
- (NSCell *)tableView:(NSTableView *)tableView dataCellForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
    LOG(@"tableView:dataCellForTableColumn:row: called");

    NSString *identifier = [tableColumn identifier];
    
    if ([identifier isEqualToString:@"task"]) {
        //LOG(@" task column setting the cell");

        LookupPopupButtonCell *cellView = [[LookupPopupButtonCell alloc] init];
        return cellView;
    }
    
    NSTextFieldCell *cellView = [tableView makeViewWithIdentifier:@"hoursCell" owner:self];
    return cellView;
    
}
@end
4

1 回答 1

0

看来您必须使用基于 VIEW 的 tableView 来获取委托消息。废话,现在要弄清楚如何将其中一个绑定到核心数据,希望它不会太难!

有没有办法为每一行重用相同的菜单?我想只要每次都没有重新创建数据源,它可能还不错,这个层次结构中仍然可能有很多行!

tableView 弹出菜单中的大纲视图

于 2013-08-14T04:16:12.920 回答