Skip to content

Instantly share code, notes, and snippets.

@drkameleon
Created September 14, 2014 08:56
Show Gist options
  • Save drkameleon/24f5207a8aa0177b284b to your computer and use it in GitHub Desktop.
Save drkameleon/24f5207a8aa0177b284b to your computer and use it in GitHub Desktop.
View-Based NSOutlineView Example
//
// AppDelegate.m
// sourceList
//
// Created by Dr.Kameleon on 9/14/14.
// Copyright (c) 2014 InSili.co. All rights reserved.
//
#import "AppDelegate.h"
/******************************************************************************
*
* NSOutlineView Extension
*
******************************************************************************/
@interface NSOutlineView (ContextMenu)
@end
@interface NSObject (NSOutlineViewContextMenuDelegate)
- (NSMenu *)outlineView:(NSOutlineView *)outlineView contextMenuForItem:(id)item;
@end
@implementation NSOutlineView (ContextMenu)
- (NSMenu *)menuForEvent:(NSEvent *)theEvent
{
int rowIndex = (int)[self rowAtPoint:[self convertPoint:[theEvent locationInWindow] fromView:nil]];
if (rowIndex >= 0)
{
[self abortEditing];
id item = [self itemAtRow:rowIndex];
if (item)
{
id obj = [self delegate];
if ([obj respondsToSelector:@selector(outlineView:shouldSelectItem:)] &&
[obj outlineView:self shouldSelectItem:item])
{
[self selectRowIndexes:[NSIndexSet indexSetWithIndex:rowIndex] byExtendingSelection:NO];
}
if ([obj respondsToSelector:@selector(outlineView:contextMenuForItem:)])
{
return [obj outlineView:self contextMenuForItem:item];
}
}
}
else // click in no man's land
{
[self deselectAll:self];
return [self menu];
}
return nil;
}
@end
/******************************************************************************
*
* Main Part
*
******************************************************************************/
@implementation AppDelegate
/*********************************
Helpers
*********************************/
#define HAS_KEY(X,Y) ([self dictionary:(X) containsKey:(Y)])
- (BOOL)dictionary:(NSDictionary*)dict containsKey: (NSString *)key {
BOOL retVal = 0;
NSArray *allKeys = [dict allKeys];
retVal = [allKeys containsObject:key];
return retVal;
}
/*********************************
Setup
*********************************/
- (void)awakeFromNib
{
// Setup Delegate/Datasource
[_fileView setDataSource:(id<NSOutlineViewDataSource>)self];
[_fileView setDelegate:(id<NSOutlineViewDelegate>)self];
[_fileView setMenu:_rightClickMenu];
// Set some sample tree data
_fileTree =
@[
@{ @"label": @"FILES", @"isGroup": @YES, @"children":@[
@{ @"label": @"one"},
@{ @"label": @"two", @"children": @[
@{@"label":@"two.1"},
@{@"label":@"two.2"}
]}
]},
@{ @"label": @"HTML", @"isGroup": @YES, @"children":@[
@{ @"label": @"one"},
@{ @"label": @"two", @"children": @[
@{@"label":@"two.1", @"children":@[
@{ @"label": @"two.1.1"},
@{ @"label": @"two.1.2"}
]},
@{@"label":@"two.2"}
]}
]},
];
// Update view
[_fileView sizeLastColumnToFit];
[_fileView setFloatsGroupRows:NO];
[_fileView reloadData];
}
/*********************************
NSOutlineView
*********************************/
//--------------------------
// Generic Setup
//--------------------------
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
{
if (HAS_KEY(item,@"children")) return YES;
else return NO;
}
- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
{
if (item==nil) return [_fileTree count]; // Root
else if (HAS_KEY(item,@"children")) return [item[@"children"] count];
else return 0;
}
- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item
{
if (item == nil) return _fileTree[index]; // Root
else if (HAS_KEY(item,@"children")) return item[@"children"][index];
else return nil;
}
- (BOOL)outlineView:(NSOutlineView *)outlineView isGroupItem:(id)item
{
if (HAS_KEY(item, @"isGroup")) return YES;
else return NO;
}
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldSelectItem:(id)item
{
if ([self outlineView:outlineView isGroupItem:item]) return NO;
else return YES;
}
//--------------------------
// Set Content & Icons
//--------------------------
- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item
{
NSTableCellView* tcv;
if ([self outlineView:outlineView isGroupItem:item]) {
tcv = [outlineView makeViewWithIdentifier:@"HeaderCell" owner:self];
tcv.textField.stringValue = item[@"label"];
}
else
{
tcv = [outlineView makeViewWithIdentifier:@"DataCell" owner:self];
tcv.textField.stringValue = item[@"label"];
NSImage* cellImage;
if (HAS_KEY(item,@"children")) cellImage = [[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(kGenericFolderIcon)];
else cellImage = [[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeRegular];
[cellImage setSize:NSMakeSize(15.0, 15.0)];
tcv.imageView.image = cellImage;
}
return tcv;
}
//--------------------------
// Selection tracking
//--------------------------
- (void)outlineViewSelectionDidChange:(NSNotification *)notification {
if ([_fileView selectedRow] != -1) {
id item = [_fileView itemAtRow:[_fileView selectedRow]];
NSLog(@"Selected item : %@",item);
}
}
//--------------------------
// Right-click menu
//--------------------------
- (NSMenu*)outlineView:(NSOutlineView*)outlineView contextMenuForItem:(id)item {
// Show menu depending on item being right-clicked
return nil;
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment