Respond to mouse events in text field in view-based table view

后端 未结 6 1326
甜味超标
甜味超标 2020-12-02 16:11

I have text fields inside a custom view inside an NSOutlineView. Editing one of these cells requires a single click, a pause, and another single click. The firs

6条回答
  •  孤城傲影
    2020-12-02 16:34

    You really want to override validateProposedFirstResponder and allow a particular first responder to be made (or not) depending on your logic. The implementation in NSTableView is (sort of) like this (I'm re-writing it to be pseudo code):

    - (BOOL)validateProposedFirstResponder:(NSResponder *)responder forEvent:(NSEvent *)event {
    
    // We want to not do anything for the following conditions:
    // 1. We aren't view based (sometimes people have subviews in tables when they aren't view based)
    // 2. The responder to valididate is ourselves (we send this up the chain, in case we are in another tableview)
    // 3. We don't have a selection highlight style; in that case, we just let things go through, since the user can't appear to select anything anyways.
    if (!isViewBased || responder == self || [self selectionHighlightStyle] == NSTableViewSelectionHighlightStyleNone) {
        return [super validateProposedFirstResponder:responder forEvent:event];
    }
    
    if (![responder isKindOfClass:[NSControl class]]) {
        // Let any non-control become first responder whenever it wants
        result = YES;
        // Exclude NSTableCellView. 
        if ([responder isKindOfClass:[NSTableCellView class]]) {
            result = NO;
        }
    
    } else if ([responder isKindOfClass:[NSButton class]]) {
        // Let all buttons go through; this would be caught later on in our hit testing, but we also do it here to make it cleaner and easier to read what we want. We want buttons to track at anytime without any restrictions. They are always valid to become the first responder. Text editing isn't.
        result = YES;
    } else if (event == nil) {
        // If we don't have any event, then we will consider it valid only if it is already the first responder
        NSResponder *currentResponder = self.window.firstResponder;
        if (currentResponder != nil && [currentResponder isKindOfClass:[NSView class]] && [(NSView *)currentResponder isDescendantOf:(NSView *)responder]) {
            result = YES;
        }
    } else {
        if ([event type] == NSEventTypeLeftMouseDown || [event type] == NSEventTypeRightMouseDown) {
            // If it was a double click, and we have a double action, then send that to the table
            if ([self doubleAction] != NULL && [event clickCount] > 1) {
               [cancel the first responder delay];
            }
       ...
              The code here checks to see if the text field 
            cell had text hit. If it did, it attempts to edit it on a delay. 
            Editing is simply making that NSTextField the first responder.
            ...
    
         }
    

提交回复
热议问题