Strange behavior using view-based NSOutline (Sourcelist) - cocoa

I have a (new in Lion) view-based NSOutlineView as Sidebar SourceList in my app using CoreData + NSTreeController + Bindings + NSOutlineView and an Object as NSOutlineViewDelegate.
I use these delegate methods in the outlineview delegate:
- (BOOL)outlineView:(NSOutlineView *)outlineView isGroupItem:(id)item In my case a item is group when the (Core Data) parent relationship is nil.
- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item To return the headercell view (group) or datacell view (icon + text).
And I set the size style of the outline view (in Interface Builder in XCode) as "Sidebar System Default" so the cellview changes its size when the user change it in the system preferences.
It works fine... but there are a few issues:
The first cellview is a group cell (header cell) and when expand-collapse the textfield for this cellview moves up-down. Only happens with the first one.
The textfield in the header cells changes it size (when changes the size in the system preferences) but I would like that the header cells size stay fixed like (Lion) Finder, Mail... does.
The string value of the textfield in the header cells doesn´t appear uppercase.
The images I use as icon in the image view of the data cells appears transparent (with a 0.5 alpha value or something like that).
Any help? Thanks in advance
SOLVED:
For the movement when the first cellview expand/collapse use the method setFloatsGroupRows:NO with the outlineview (Thanks Anton!)
If you want fixed size for the font of the groupcells (even if user change it in the system preferences) unbind in IB the header cell with its Table Cell View.
Using a valueTransformer (that transform a string to uppercase) with the header cell the string will appear uppercase. Also you can do this with the nsoutlineview datasource method - outlineView:objectValueForTableColumn:byItem:...
And finally the icon is semi-transparent because is not enabled. Uncheck "Conditionally Sets Enabled" in the Value or Value Path (depending the one you use) in the image cell bindings

Setting setFloatsGroupRows:NO for the outline view must solve the issue with first group item moving up-down when being expanded/collapsed.

In case it's not obvious to anyone:
"Floats group rows" in Interface Builder:
You can set "Floats group rows" directly in Interface Builder.
select your Source List in Interface Builder's document outline.
show the Attributes Inspector, and you will find the "Floats Group Rows" checkbox. Untick it, and your nasty jumping group headings suddenly behave themselves :)
In Swift:
Alternatively, if you're in Swift, you can do something like:
#IBOutlet weak var sourceList: NSOutlineView!
sourceList.floatsGroupRows = false

You may also have a look at the answer of this question: NSOulineView header cell font The automatic style unselect-reselect dance worked for me.

I was wondering how you achieved the source list that's visible on the screenshot.
I have created a little sample project, which does the same and includes the feedback from #anton-ivanov:
Display a list of items
Edit the items in a master-detail fashion
Remove and add items
Usage of bindings
Check out besi/mac-quickies on github.
Most of the stuff is either done in IB or can be found in the AppDelegate

Related

How to remove translucency that appairs on some parts of a NSTableView?

I'm working on a project for macOS with Storyboards where I have a custom view containing a NSTableView and some other controls.
The customView background is colored in viewWillAppear():
backgroundCustomView.layer?.backgroundColor = NSColor.white.cgColor
The problem is that the items of the NSTableView appears with some translucent parts inside them.
I would like to prefer that the NSTableView appears without any translucency (this is the reason because I put a custom view under the NSTableView).
I tried to change in IB about all what I think could be related options without any luck.
PS
The discontinued translucency between the items is due by the cell spacing option.
You need to specified that you view needs a layer as its backing store
backgroundCustomView.wantsLayer = true
backgroundCustomView.layer?.backgroundColor = NSColor.white.cgColor
More info at wantsLayer property documentation page

How to remove NSTableView's border and change cell selection color as same as Finder's?

I'm making an Cocoa app for Yosemite.
I added a view based NSTableView in Interface builder, but the border 2 pixel width and thicker than Yosemite's Finder's.
And the cell selection color is blue, while Yosemite's Finder's is gray.
And this is how Yosemite's Finder's table view looks like.
I checked the settings in Interface Builder.
The super scroll view of NSTableView's frame setting is (0,0,149,257):
While the Clip View's frame setting is (1, 1, 147, 255) and can not be changed.
And how to make a same NSTableView as Yosemite's Finder's?
Thanks a ton!
The Finder sidebar isn't a table-view it's a Source List NSOutlineView:
The border is applied around the enclosing scroll view:
Note also that a standard NSOutlineView lets you adjust the highlight style from within Interface Buider:
In my experience selected rows are still painted blue, even when the "Source List" highlight style is selected. To avoid that, I needed to prevent the table or outline view from becoming the first responder by subclassing it and adding
- (BOOL)becomeFirstResponder {
return NO;
}
Edit:
Turns out becomeFirstResponder is actually important if you want to support keyboard navigation. I have found a better solution that does not override becomeFirstResponder.
First, create a custom NSTableRowView subclass with an (overridden) empty setEmphasized: method:
- (void)setEmphasized:(BOOL)emphasized {
// This avoids a blue background when selected in a source list that has first responder status.
}
You can then provide an instance of your custom NSTableRowView class by implementing
- (NSTableRowView *)tableView:(NSTableView *)tableView rowViewForRow:(NSInteger)row
in your NSTableViewDelegate.
To whoever wants to remove the NSTableView border...
My requirement was to remove the border colour of the NSTableView so that, it should look like a white box. Tried all properties and forums but couldn't find a way to do that. Finally I came up with a dirty hack in the Storyboard which could fix the problem. If someone have a better option, please let us know.
Embed the NSTableView in a CustomBox. Set the Box BorderType as 'None'
Then set the constraints (Left, Top, Right and Bottom) of NSTableView to the containing Box. Set the values to -2. so that the NSTableView border will be outside of the Box
Now in Storyboard, select the 'clipView(NSClipView)' of the NSTableView. clipView is the superView of the NSTableView
Go to the Size Inspector and uncheck the 'Automatically Adjust' property of the "Content Insets"
Set the values to Left=2, Top=2, Bottom=-2 and Right=-2
Thats it.

how do i stop NSTextField blocking right clicks for NSTableView rows?

As the title suggest, I've enabled right clicks for my tableview with customized rows. Anywhere there is an NSTextField, it blocks the right click.
is there a userInteractionEnabled equivalent for cocoa like on the iphone?
I though I probably needed to subclass everything in my NSTableCellView subclass, but I just needed to override -(NSView*)hitTest:(NSPoint)aPoint method in my NSTableCellView subclass to return self.
I'm able to right click on text fields within my custom view based table view cell. Here is how I configure it:
NSTextField *tf = [[NSTextField alloc] initWithFrame:NSZeroRect];
self.textField = tf;
self.imageView.autoresizingMask=NSViewWidthSizable;
self.textField.editable=NO;
self.textField.selectable=NO;
self.textField.drawsBackground=NO;
self.textField.bordered=NO;
self.textField.bezeled=NO;
self.textField.target=self;
self.textField.action=#selector(textDidEndEditing:);
[self.textField.cell setLineBreakMode:NSLineBreakByTruncatingMiddle];
Also, make sure you are setting the -menu property of NSTableView and not the cell view to enable to menu. (I don't know if that will make a difference to your issue but it is how I do right clicking in a table view.)

Which Cocoa control to use to display drill-down table?

Any idea which Cocoa control to use to display the drill-down table as in attached screenshot? On the left panel is a list of items. When an item is selected, the detail of the item is displayed on the right panel. Is it NSOutlineView or NSBrowser? Thanks!
Screenshot http://s1.proxy03.twitpic.com/photos/large/409079140.png
Link to twitpic page
It's an NSTableView on the left, and most likely an NSTextView on the right. The NSTableView on the left most likely has an NSDateFormatter set for the cell in the third column, which handles converting an NSDate object into the NSString value that's shown.
See Table View Programming Guide for more general info on NSTableViews. There is also NSOutlineView, which is a subclass of NSTableView, for when you need to display a data tree. Implementing a table view is much easier than an outline view or NSBrowser, so only go with an outline view if you really need to.
NSOutlineView will produce something like the left panel, but is probably overkill judging by your screenshot.
NSBrowser would give you a Finder-style drill down.
I would personally use two views - an NSTableView on the left and an NSTextView on the right.

How to resize UI Table View of a UI Table View Controller programmatically?

I subclassed UITableViewController and called it FeaturedGamesViewController. Ok, I also have a navigation controller to which I added this FeaturedGamesViewController as the root. All pretty standard stuff that you do in the App Delegate.
Also note that there is no NIB file created for FeaturedGamesViewController. Just subclassing UITableViewController and calling initWithStyle sets the style of the table and sets the dataSource and delegate and size automatically. Data Source and Delegate are obviously set to FeaturedGamesViewController.
- (id)init
{
// Call the superclass's designated initializer
[super initWithStyle:UITableViewStyleGrouped];
}
OK, You see that I have set the table size to "Grouped". In Landscape view on my iPad it has about 20 pixels of space to the top, left and right (Sorry can't post screen shot because I am new here and the system won't let me until I have accumulated a certain number of points)
I DO NOT want that! This is Landscape so I expect it to fill up the all the space between the navigation bar and the tab bar below. What is worse is that I have faked a grid with a Custom UITableViewCell but the space to the left and right make it so that if you click on that space, the entire row is selected thus betraying the sense that this is a grid.
Now I figure I should resize the table view in viewDidLoad or something but I don't know how. I cannot do initWithFrame because of potential memory leaks (and possibly resetting dataSource and delegate and autoresizeMask properties that were already set) so there must be a setter or something to reset the origin of the tableview to just beneath the Navigation bar and filling up the entire screen with size 1024X748. How do you do dynamically reset the size of the table view?
Then I got really frustrated and I decided to do it via a Nib file, that way I can set the the orientation to landscape and set simulated Navigation and Tab bars and fill the rest of the space with the table view. This worked! If you are curious how to create a table view with a Nib after you have subclassed UITableViewController WITHOUT a nib, here is how:
http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/TableView_iPhone/CreateConfigureTableView/CreateConfigureTableView.html#//apple_ref/doc/uid/TP40007451-CH6-SW10
Go to the paragraph right before "Creating a Table View Programmatically".
OK, when I did that, my landscape view of the "grid" looks filled up the entire space between the navigation bar at the top and the tab bar at the bottom just like I wanted.
I was fiddling with this some more and I found out that in my "non nib" version (the problematic one), I had set the table style to "grouped". When I changed it to "plain", it worked!!! But here is the thing though: In the nib version, "grouped" or "plain" gives the correct layout with the table occupying the whole space. So what gives?
Sorry for the long question but I guess what I am asking is:
1) How do you programmatically reset the size of the table view without introducing potential memory leaks or affecting other properties already set for you (ex: dataSource, delegate, autoResizeMask - these are set for you just because you subclassed UITableViewController)?
2) How do you do that for any view in general?
3) Why does "plain" style fill the layout as desired whereas "grouped" style gives the weird layout. Note that it this is not a problem in the Nib version.
Thanks for your patience!
Answer for (2), and hence for (1):
A UIView's frame is in a local coordinate system of its superview. A common way to make a view fit its superview is
CGRect bounds = [[self superview] bounds];
[self setFrame:bounds];
You should do this inside layoutSubviews.

Resources