how do I remove the space between cells of an NSTableView?
Asked Answered
F

2

10

I have set the intercell spacing in my NSTableView to 0 by sending:

[self.tableView setIntercellSpacing:NSMakeSize(0, 0)];

in the window controller's awakeFromNib but there is still an (possibly 1 pixel wide) empty space between the rows, which I think is where the grid lines are drawn although I'm not using the grid lines. How can I get rid of this space between the rows?

update:

The NSTableView documentation seems to say that this 1 pixel separation should go away when the intercell separation is set to 0, 0. In my case, its not. Maybe it's a bug?

Francklyn answered 7/12, 2012 at 5:29 Comment(5)
are you using [self.tableView setIntercellSpacing:NSMakeSize(0, 0)]; method in awakefromnib?Gilberto
Yes, I updated the question to include this info.Francklyn
Dang, I just realized that the 1 pixel gap was due to a bug in my drawing code. How can I withdraw this question?Francklyn
@MikeT You asked an interesting question (or rather I think it's interesting), and it'd be a shame to see it disappear; it could help others. Why not present your bug as an answer, and once the wait interval passes, accept your own answer?Ovate
You can also just set it to NSZeroSize!Grainy
F
5

As suggested by trudyscousin, I'll post how I fixed my problem:

As it turns out, the empty space does in fact disappear when you set the intercell spacing to 0 as I did. My problem was that the drawing code in my NSTableCellView subclass wasn't drawing all the way to the edge of the view. The gap I was seeing wasn't the intercell separation, it was the border of my NSTableCellView subclass.

Francklyn answered 9/12, 2012 at 8:33 Comment(0)
F
1

In my case the task was to have 0.5 pt (1 px on Retina display) separator. Seems even when intercellSpacing set to .zero (or 0.5 pt in my case) AppKit still preserving 1 pt space between rows when drawing selection.

I ended up by subclassing NSTableRowView. With custom row I can set separator to any height. Here is a Swift 4.2 example:

class WelcomeRecentDocumentsView: View {

   private lazy var tableView = TableView().autolayoutView()
   private lazy var scrollView = ScrollView(tableView: tableView).autolayoutView()

   override var intrinsicContentSize: NSSize {
      return CGSize(width: 240, height: 400)
   }

   private var recentDocumentsURLs = (0 ..< 10).map { $0 }
}

extension WelcomeRecentDocumentsView: NSTableViewDataSource {

   func numberOfRows(in tableView: NSTableView) -> Int {
      return recentDocumentsURLs.count
   }

   func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
      return tableView.makeView(ItemView.self)
   }

}

extension WelcomeRecentDocumentsView: NSTableViewDelegate {

   func tableView(_ tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? {
      // Returning custom RowView.
      return RowView(separatorHeight: separatorHeight, separatorColor: tableView.gridColor)
   }
}

extension WelcomeRecentDocumentsView {

   private var separatorHeight: CGFloat {
      return convertFromBacking(1)
   }

   override func setupUI() {
      addSubview(scrollView)

      let column = NSTableColumn(identifier: "com.example.column", resizingMask: .autoresizingMask)
      tableView.addTableColumn(column)
      tableView.columnAutoresizingStyle = .uniformColumnAutoresizingStyle
      tableView.headerView = nil
      tableView.setAutomaticRowHeight(estimatedHeight: ItemView.defaultHeight)
      tableView.intercellSpacing = CGSize(height: separatorHeight)
      tableView.gridStyleMask = .solidHorizontalGridLineMask
   }

   override func setupHandlers() {
      tableView.delegate = self
      tableView.dataSource = self
   }

   override func setupLayout() {
      LayoutConstraint.pin(to: .bounds, scrollView).activate()
   }

   override func setupDefaults() {
      tableView.sizeLastColumnToFit()
   }
}

extension WelcomeRecentDocumentsView {

   class RowView: NSTableRowView {

      let separatorHeight: CGFloat
      let separatorColor: NSColor

      init(separatorHeight: CGFloat = 1, separatorColor: NSColor = .gridColor) {
         self.separatorHeight = separatorHeight
         self.separatorColor = separatorColor
         super.init(frame: .zero)
      }

      required init?(coder decoder: NSCoder) {
         fatalError()
      }

      override func drawSelection(in dirtyRect: NSRect) {
         let rect = bounds.insetBottom(by: -separatorHeight)
         NSColor.alternateSelectedControlColor.setFill()
         rect.fill()
      }

      override func drawSeparator(in dirtyRect: NSRect) {
         let rect = bounds.insetTop(by: bounds.height - separatorHeight)
         separatorColor.setFill()
         rect.fill()
      }

   }

   class ItemView: View {

      static let defaultHeight: CGFloat = 52

      override var intrinsicContentSize: NSSize {
         return CGSize(intrinsicHeight: type(of: self).defaultHeight)
      }
   }
}
Frankiefrankincense answered 21/9, 2018 at 4:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.