Skip to content

Instantly share code, notes, and snippets.

@Ceylo
Created December 28, 2019 18:42
Show Gist options
  • Save Ceylo/c66b10a9bd908448a7842ad5ae111387 to your computer and use it in GitHub Desktop.
Save Ceylo/c66b10a9bd908448a7842ad5ae111387 to your computer and use it in GitHub Desktop.
import Cocoa
private func rowIndexForLayer(at rowIndex: Int, in layers: [Layer]) -> Int {
return layers.count - 1 - rowIndex
}
private func outlineViewRowIndex(for path: IndexPath, parent: LayerContainer) -> Int {
let layerIndex = path.last!
return rowIndexForLayer(at: layerIndex, in: parent.layers)
}
func rowIndexesForMoving(_ layer: Layer, from: IndexPath, below: IndexPath,
sourceContainer: LayerContainer, destinationContainer: LayerContainer)
-> (fromRow: Int, fromParent: LayerContainer?, toRow: Int, toParent: LayerContainer?)?
{
guard from.next != below else { return nil }
guard from != below else { return nil }
let updatedFrom = from.parent == below.parent ? from.havingInserted(below) : from
var fromRow = outlineViewRowIndex(for: updatedFrom,
parent: sourceContainer)
let updatedBelow = from.parent == below.parent ? below.havingRemoved(from) : below
let toRow = outlineViewRowIndex(for: updatedBelow,
parent: destinationContainer)
if sourceContainer === destinationContainer && toRow > fromRow {
fromRow += 1
}
if sourceContainer !== destinationContainer {
fromRow += 1
}
guard fromRow != toRow || sourceContainer !== destinationContainer else { return nil }
let fromParent = from.count > 1 ? sourceContainer : nil
let toParent = below.count > 1 ? destinationContainer : nil
return (fromRow, fromParent, toRow, toParent)
}
extension NSOutlineView {
/// Convenience API for the similar `NSOutlineView.moveItem(at:inParent:to:inParent:)`, but in Canvas
/// coordinates.
///
/// Canvas coordinates refer to the fact that the first layer (index 0) in canvas is the background one (ie. below other layers),
/// although it is displayed as the last one in the outline view (ie. the bottom layer is the background).
///
/// - Parameters:
/// - layer: The layer being moved.
/// - canvas: The canvas to which the layer belongs.
/// - sourcePath: The original path to the layer, in Canvas coordinates.
/// - destinationPath: The destination path at which the layer is inserted, in Canvas coordinates.
func move(_ layer: Layer, in canvas: Canvas, at sourcePath: IndexPath, below destinationPath: IndexPath,
sourceContainer: LayerContainer, destinationContainer: LayerContainer) {
if let (fromRow, fromParent, toRow, toParent)
= rowIndexesForMoving(layer, from: sourcePath, below: destinationPath,
sourceContainer: sourceContainer,
destinationContainer: destinationContainer) {
moveItem(at: fromRow, inParent: fromParent, to: toRow, inParent: toParent)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment