mirror of
https://github.com/arsenetar/dupeguru-cocoa.git
synced 2024-11-14 11:49:02 +00:00
191 lines
5.6 KiB
Objective-C
191 lines
5.6 KiB
Objective-C
/*
|
|
Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
|
|
|
|
This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
|
|
which should be included with this package. The terms are also available at
|
|
http://www.gnu.org/licenses/gpl-3.0.html
|
|
*/
|
|
|
|
#import "HSOutlineView.h"
|
|
|
|
@implementation HSOutlineView
|
|
- (id <HSOutlineViewDelegate>)delegate
|
|
{
|
|
return (id <HSOutlineViewDelegate>)[super delegate];
|
|
}
|
|
|
|
- (void)setDelegate:(id <HSOutlineViewDelegate>)aDelegate
|
|
{
|
|
[super setDelegate:aDelegate];
|
|
id delegate = [self delegate];
|
|
if ([delegate respondsToSelector:@selector(outlineViewWasDoubleClicked:)]) {
|
|
[self setTarget:[self delegate]];
|
|
[self setDoubleAction:@selector(outlineViewWasDoubleClicked:)];
|
|
}
|
|
}
|
|
/* NSOutlineView overrides */
|
|
- (void)keyDown:(NSEvent *)event
|
|
{
|
|
if (![self dispatchSpecialKeys:event])
|
|
{
|
|
[super keyDown:event];
|
|
}
|
|
}
|
|
|
|
- (BOOL)shouldEditTableColumn:(NSTableColumn *)column row:(NSInteger)row
|
|
{
|
|
BOOL result = [super shouldEditTableColumn:column row:row];
|
|
if (!result)
|
|
return result;
|
|
id delegate = [self delegate];
|
|
if ([delegate respondsToSelector:@selector(outlineView:shouldEditTableColumn:item:)])
|
|
return [delegate outlineView:self shouldEditTableColumn:column item:[self itemAtRow:row]];
|
|
return YES;
|
|
}
|
|
|
|
/* Notifications & Delegate */
|
|
- (void)textDidEndEditing:(NSNotification *)notification
|
|
{
|
|
notification = [self processTextDidEndEditing:notification];
|
|
NSView *nextKeyView = [self nextKeyView];
|
|
[self setNextKeyView:nil];
|
|
[super textDidEndEditing:notification];
|
|
[self setNextKeyView:nextKeyView];
|
|
|
|
if ([self editedColumn] == -1)
|
|
{
|
|
if (!manualEditionStop)
|
|
{
|
|
id delegate = [self delegate];
|
|
if ([delegate respondsToSelector:@selector(outlineViewDidEndEditing:)])
|
|
{
|
|
[delegate outlineViewDidEndEditing:self];
|
|
}
|
|
}
|
|
// We may have lost the focus
|
|
[[self window] makeFirstResponder:self];
|
|
}
|
|
}
|
|
|
|
- (BOOL)textView:(NSTextView *)textView doCommandBySelector:(SEL)command
|
|
{
|
|
if (command == @selector(cancelOperation:))
|
|
{
|
|
[self stopEditing]; // The stop editing has to happen before the cancelEdits
|
|
id delegate = [self delegate];
|
|
if ([delegate respondsToSelector:@selector(outlineViewCancelsEdition:)])
|
|
{
|
|
[delegate outlineViewCancelsEdition:self];
|
|
}
|
|
return YES;
|
|
}
|
|
return NO;
|
|
}
|
|
|
|
/* Public */
|
|
- (NSIndexPath *)selectedPath
|
|
{
|
|
NSInteger row = [self selectedRow];
|
|
return [self itemAtRow:row];
|
|
}
|
|
|
|
- (void)selectPath:(NSIndexPath *)aPath
|
|
{
|
|
[self selectNodePaths:[NSArray arrayWithObject:aPath]];
|
|
}
|
|
|
|
- (NSArray *)selectedNodePaths
|
|
{
|
|
NSMutableArray *r = [NSMutableArray array];
|
|
NSIndexSet *indexes = [self selectedRowIndexes];
|
|
NSInteger i = [indexes firstIndex];
|
|
while (i != NSNotFound) {
|
|
NSIndexPath *path = [self itemAtRow:i];
|
|
[r addObject:path];
|
|
i = [indexes indexGreaterThanIndex:i];
|
|
}
|
|
return r;
|
|
}
|
|
|
|
- (void)selectNodePaths:(NSArray *)aPaths
|
|
{
|
|
NSMutableIndexSet *toSelect = [NSMutableIndexSet indexSet];
|
|
/* To ensure that we have correct row indexes, we must first expand all paths, and *then* select
|
|
* row indexes.
|
|
**/
|
|
for (NSIndexPath *path in aPaths) {
|
|
[self ensureExpanded:path];
|
|
}
|
|
for (NSIndexPath *path in aPaths) {
|
|
[toSelect addIndex:[self rowForItem:path]];
|
|
}
|
|
[self selectRowIndexes:toSelect byExtendingSelection:NO];
|
|
if ([toSelect count] > 0) {
|
|
[self scrollRowToVisible:[toSelect firstIndex]];
|
|
}
|
|
}
|
|
|
|
- (void)ensureExpanded:(NSIndexPath *)aPath
|
|
{
|
|
/* Expands aPath and make sure that its parent items are expanded as well.
|
|
*/
|
|
id <HSOutlineViewDelegate> delegate = [self delegate];
|
|
NSIndexPath *tmppath = [NSIndexPath indexPathWithIndex:[aPath indexAtPosition:0]];
|
|
[self expandItem:[delegate internalizedPath:tmppath]];
|
|
for (NSInteger i=1; i<[aPath length]; i++) {
|
|
tmppath = [tmppath indexPathByAddingIndex:[aPath indexAtPosition:i]];
|
|
[self expandItem:[delegate internalizedPath:tmppath]];
|
|
}
|
|
}
|
|
|
|
- (void)stopEditing
|
|
{
|
|
// If we're not editing, don't do anything because we don't want to steal focus from another view
|
|
if ([self editedColumn] >= 0)
|
|
{
|
|
manualEditionStop = YES;
|
|
[[self window] makeFirstResponder:self]; // This will abort edition
|
|
manualEditionStop = NO;
|
|
}
|
|
}
|
|
|
|
- (void)updateSelection
|
|
{
|
|
id delegate = [self delegate];
|
|
if ([delegate respondsToSelector:@selector(selectedIndexPaths)]) {
|
|
[self selectNodePaths:[delegate selectedIndexPaths]];
|
|
}
|
|
}
|
|
|
|
/* Actions */
|
|
|
|
- (IBAction)copy:(id)sender
|
|
{
|
|
NSString *data = [[self delegate] dataForCopyToPasteboard];
|
|
if (data != nil) {
|
|
NSPasteboard *p = [NSPasteboard generalPasteboard];
|
|
[p declareTypes:[NSArray arrayWithObjects:NSPasteboardTypeString, nil] owner:nil];
|
|
[p setString:data forType:NSPasteboardTypeString];
|
|
}
|
|
}
|
|
|
|
/* BIG HACK ZONE
|
|
When tracking clicks in the NSTextField, the NSTableView goes in edition mode even if we click on the
|
|
arrow or the button. The only way I found to avoid this is this scheme: let the HSOutlineView know
|
|
of the event that caused the click, and don't go in edit mode if it happens.
|
|
*/
|
|
|
|
- (void)ignoreEventForEdition:(NSEvent *)aEvent
|
|
{
|
|
eventToIgnore = aEvent;
|
|
}
|
|
|
|
- (void)editColumn:(NSInteger)columnIndex row:(NSInteger)rowIndex withEvent:(NSEvent *)theEvent select:(BOOL)flag
|
|
{
|
|
if ((theEvent != nil) && (theEvent == eventToIgnore))
|
|
return;
|
|
[super editColumn:columnIndex row:rowIndex withEvent:theEvent select:flag];
|
|
}
|
|
|
|
@end
|