Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSOutlineView with transparent field editor

I'm working with a NSOutlineView located on a HUD panel. I configured it so that it doesn't draw its background. Everything looks fine until I double click to edit a cell. The field editor draws its background and focus ring which completely ruin the whole user experience.

This is what I'm doing in the subclass of NSTextFieldCell:

- (NSText *)setUpFieldEditorAttributes:(NSText *)textObj
{   
    NSText *text = [super setUpFieldEditorAttributes:textObj];

    [text setDrawsBackground:YES];
    [text setBackgroundColor:[NSColor darkGrayColor]];

    return text;
}

If I use setDrawsBackground:NO it's completely ignored and I get a white background. My solution is far from being good because I can't touch the alpha component of the color (if I do that, again the field editor will use another color as a background), but at least I don't get a white background.

I'm wondering if there's an actual solution to this problem. Do I have to provide my own field editor? Is it worth it?

What I want is simply a field editor with no background and no focus ring, just the cursor blinking.

Thanks!

like image 781
Etabubu Avatar asked Oct 11 '22 10:10

Etabubu


1 Answers

The problem is that the white background is drawn by NSTableView when it's sent -editColumn:row:withEvent:select:. It fills the cell's rect with +[NSColor textBackgroundColor].

If there's a public API for overriding the current setting for named colors from the developer colorspace, we could set it inside an override of -editColumn:row:withEvent:select: or the like. I do not recall such an API (pointers are appreciated). ALSO: I've only tested this code on Snow Leopard (even the Leopard SDK addendum below). Verify the code against the actual SDKs and runtime environments you intend to support.

NSTableView has a private accessor it uses for the fill color, but it's a read-only property. No setter, so we can't just change the value on a standard NSTableView. We must subclass it. (Since you want the same behavior in an outlineView and NSOutlineView is already a subclass of NSTableView, we're going to subclass NSOutlineView. But, aside from the superclass, the code is identical.)

@interface ASCOutlineView : NSOutlineView {

}

@end

@implementation ASCOutlineView

- _textBackgroundColor
{
    return  ([NSColor clearColor]);
}

@end

seems to be all one needs to prevent that glaring white block from ruining your HUD when editing table cells in Snow Leopard.

Apps compiled against the Leopard SDK need a little more support though. Leopard's tableViews may have hard-coded some rendering properties so we need to override a choice method.

NSTextFieldCells are actually wrappers for NSTextViews so they can be used inside controls. They normally share the same textView instance, which is managed by the window (or its subclass, panel, in this case). NSTableView alters the settings of the NSTextFieldCell to conform to system UI settings for editing data. Mostly. The NSTextFieldCell then propagates those settings to the NSTextView. At any point along this pipeline we can override a method or two to alter the values of those properties to match our own UI.

I use -[NSTextFieldCell setDrawsBackground:] because it requires little effort to get correct. It's also important to keep the internal state as consistent with the effect we're hoping to achieve in the event some other object might depend on that state.

@interface ASCTextFieldCell : NSTextFieldCell {

}

@end

@implementation ASCTextFieldCell

- (void)setDrawsBackground: (BOOL)flag
{
    [super setDrawsBackground: NO];
}

@end

And preventing the focus ring from appearing while the cell's being edited is a simple matter of changing the setting of its focus ring type. Frustratingly, IB doesn't provide access to this property, so it must be done programmatically:

for(eachColumn in [hudOutlineView tableColumns])
{
    columnCell = [[ASCTextFieldCell alloc] initTextCell: @""];
    [eachColumn setDataCell: columnCell];

    if([columnCell respondsToSelector: @selector(setFocusRingType:)] != NO)
        [(NSTextFieldCell *)columnCell setFocusRingType: NSFocusRingTypeNone];
}
like image 186
Huperniketes Avatar answered Nov 03 '22 00:11

Huperniketes