1

At the moment I have an NSTableView with a custom NSTextFieldCell that holds an NSAttributedString with some ranges with the NSLinkAttribute. I tried to integrate code from Apple's TableViewLinks example and Toomas Vather's HyperlinkTextField.

I implemented the -trackMouse Function like this:

- (BOOL)trackMouse:(NSEvent *)theEvent inRect:(NSRect)cellFrame ofView:(NSView *)controlView untilMouseUp:(BOOL)flag {

BOOL result = YES;
NSUInteger hitTestResult = [self hitTestForEvent:theEvent inRect:cellFrame ofView:controlView];
if ((hitTestResult & NSCellHitContentArea) != 0) {
    result = [super trackMouse:theEvent inRect:cellFrame ofView:controlView untilMouseUp:flag];
    theEvent = [NSApp currentEvent];
    hitTestResult = [self hitTestForEvent:theEvent inRect:cellFrame ofView:controlView];
    if ((hitTestResult & NSCellHitContentArea) != 0) {
        NSAttributedString* attrValue = [self.objectValues objectForKey:@"theAttributedString"];
        NSMutableAttributedString* attributedStringWithLinks = [[NSMutableAttributedString alloc] initWithAttributedString:attrValue];

        //HOW TO GET A RIGHT INDEX?
        NSTableView* myTableView = (NSTableView *)[self controlView];
        NSPoint eventPoint = [myTableView convertPoint:[theEvent locationInWindow] fromView:nil];
        NSInteger myRow = [myTableView rowAtPoint:eventPoint];
        NSRect myBetterViewRect = [myTableView rectOfRow:myRow];


        __block NSTextView* myTextView = [[NSTextView alloc] initWithFrame:myBetterViewRect];
        [myTextView.textStorage setAttributedString:attributedStringWithLinks];

        NSPoint localPoint = [myTextView convertPoint:eventPoint fromView:myTableView];
        NSUInteger index = [myTextView.layoutManager characterIndexForPoint:localPoint inTextContainer:myTextView.textContainer fractionOfDistanceBetweenInsertionPoints:NULL];

        if (index != NSNotFound)
        {
            NSMutableArray* myHyperlinkInfos = [[NSMutableArray alloc] init];
            NSRange stringRange = NSMakeRange(0, [attrValue length]);
            [attrValue enumerateAttribute:NSLinkAttributeName inRange:stringRange options:0 usingBlock:^(id value, NSRange range, BOOL* stop)
             {
                 if (value)
                 {
                     NSUInteger rectCount = 0;
                     NSRectArray rectArray = [myTextView.layoutManager rectArrayForCharacterRange:range withinSelectedCharacterRange:range inTextContainer:myTextView.textContainer rectCount:&rectCount];
                     for (NSUInteger i = 0; i < rectCount; i++)
                     {
                         [myHyperlinkInfos addObject:@{kHyperlinkInfoCharacterRangeKey : [NSValue valueWithRange:range], kHyperlinkInfoURLKey : value, kHyperlinkInfoRectKey : [NSValue valueWithRect:rectArray[i]]}];
                     }
                 }
             }];

            for (NSDictionary* info in myHyperlinkInfos)
            {
                NSRange range = [[info objectForKey:kHyperlinkInfoCharacterRangeKey] rangeValue];
                if (NSLocationInRange(index, range))
                {
                    NSURL* url = [NSURL URLWithString:[info objectForKey:kHyperlinkInfoURLKey]];
                    [[NSWorkspace sharedWorkspace] openURL:url];
                }
            }
        }
    }
}
return result;}

The character-Index when clicking into the cell's (nstextview's) text appears not to fit. So even if there are more than one link in the text, usually the last link is opened. My guess is that I don´t get the nsrect of the clicked cell. If so, how could I get the right NSRect?

I am glad for any suggestions, comments, code pieces - or simpler solutions (even if this would include switching to a view-based tableview).

Thanks.

david.has
  • 11
  • 1

0 Answers0