Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Floating Rows for NSOutlineView

This Swift package provides floating header rows for AppKit’s NSOutlineView. The idea is the same as floatsGroupRows for NSTableView, but extended to support a multi-level stack of floating rows.

Demo.mp4

Usage

This library only manages the row stack; the views for the floating rows are left up to you.

An example usage for a view controller that manages an outline view could look like this:

import FloatingRowStack

final class SomeViewController: NSViewController {
    // ...
    
    private var floatingRowStack: FloatingRowStack? = nil
    
    private func someSetup() {
        self.floatingRowStack = FloatingRowStack(
            outlineView: self.outlineView,
            configuration: FloatingRowStack.Configuration(
                stackRowHeight: 22.0,
                minDescendantsHeight: 3.0 * 22.0),
            containerView: self.floatingView,
            makeRowView: { [weak self] level, item in
                guard level <= 2 else {
                    return nil
                }
                return self?.makeFloatingStackRowView(level: level, item: item)
            })
    }
}

The following is an example SwiftUI implementation for the containerView:

import SwiftUI

struct FloatingView: View {
    let contentView: NSView
    
    var body: some View {
        StaticViewRepresentation(view: self.contentView)
            .background {
                Canvas { canvas, size in
                    let stackRowHeight = 22.0
                    
                    func drawLine(y: CGFloat, inset: CGFloat) {
                        let line = Path {
                            $0.move(to: CGPoint(x: inset, y: y))
                            $0.addLine(to: CGPoint(x: size.width - inset, y: y))
                            $0.addLine(to: CGPoint(x: size.width - inset, y: y - 1.0))
                            $0.addLine(to: CGPoint(x: inset, y: y - 1.0))
                            $0.closeSubpath()
                        }
                        canvas.fill(line, with: .color(Color(NSColor.separatorColor)))
                    }
                    
                    for y in stride(from: stackRowHeight, to: size.height, by: stackRowHeight) {
                        drawLine(y: y, inset: 16.0)
                    }
                    
                    drawLine(y: size.height, inset: 0)
                }
            }
            .background(.regularMaterial)
            .background(alignment: .bottom) {
                // shadow below floating row stack
                LinearGradient(
                    colors: [.black.opacity(0.5), .black.opacity(0.0)],
                    startPoint: .top,
                    endPoint: .bottom)
                .frame(height: 12.0)
                .offset(y: 12.0)
            }
    }
}

struct StaticViewRepresentation: NSViewRepresentable {
    let view: NSView
    
    func makeNSView(context: Context) -> some NSView {
        self.view
    }
    
    func updateNSView(_ nsView: NSViewType, context: Context) {}
}

The above FloatingView would be used like this:

let floatingView = FloatingView(contentView: NSView())

self.floatingRowStack = FloatingRowStack(
    // ...
    containerView: NSHostingView(rootView: floatingView),
    contentView: floatingView.contentView,
    // ...
)

About

Swift package for stacked floating rows in an NSOutlineView.

Resources

Stars

12 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages