Post

Replies

Boosts

Views

Activity

Reply to Observe a tree of Core Data relationships?
Yes, there was an option I missed. NSTreeController seems to handle this really well, with a few small quirks. I had to add a 'rules' property to my rule. Simple extension: extension Rule { @objc public var rules: NSSet? { return self.passToLayer?.rules } } Setting up the binding was a little weird, as I've never done that in code before. Wound up with roughly this: @IBOutlet var ruleViewContainer:NSView! var ruleOutlineView:NSOutlineView = NSOutlineView() private var layerToShow:Layer private var treeController:NSTreeController = NSTreeController() ... override func viewWillAppear() { ... let outlineContainer = NSScrollView(frame:ruleViewContainer.bounds) outlineContainer.autoresizingMask = [.width, .height] outlineContainer.documentView = ruleOutlineView outlineContainer.hasVerticalScroller = true outlineContainer.hasHorizontalScroller = true ruleViewContainer.addSubview(outlineContainer) ruleOutlineView.usesAlternatingRowBackgroundColors = true ruleOutlineView.usesAutomaticRowHeights = true ruleOutlineView.delegate = self ruleOutlineView.dataSource = self ruleOutlineView.doubleAction = #selector(self.doubleClick) ruleOutlineView.target = self treeController.childrenKeyPath = "rules" treeController.bind(NSBindingName.content, to: layerToShow, withKeyPath: "rules", options: nil) ruleOutlineView.bind(NSBindingName.content, to: treeController, withKeyPath: "arrangedObjects", options: nil) } Now all the items in the NSOutlineView are of type NSTreeNode. This broke my existing drag-and-drop and outlineView(_ outlineView:, viewFor tableColumn:, item:). Easy enough to fix. Just wrap all the references to item like this: let representedItem = (item as! NSTreeNode).representedObject Then use representedItem just like you used item before. I handle the updates in my API interaction object, which then updates my Core Data store if the server confirms the attempted change was successful. The UI then updates. I still have a few weird glitches. Moved objects are sometimes out of order. That should be much easier to figure out, though.
Aug ’21
Reply to Color swatches in SwiftUI picker?
Figured it out. I used a modified version of this NSImage+TintColor extension to create a swatch dictionary: let namedColors:[String] = [ "aquamarine", "black", "blue", ... } let myColorSwatches:[String:NSImage] = { (colorNames:[String]) -> [String:NSImage] in var toReturn:[String:NSImage] = [:] for colorName in colorNames { let image = NSImage(systemSymbolName: "rectangle.fill", accessibilityDescription: nil)! image.isTemplate = false image.lockFocus() NSColor(named: colorName)!.set() let imageRect = NSRect(origin: .zero, size: image.size) imageRect.fill(using: .sourceIn) image.unlockFocus() toReturn[colorName] = image } return toReturn }(namedColors) ... which I can then reference in my SwiftUI Picker: Picker("Color:", selection: pickerColor) { ForEach(namedColors, id: \.self) { colorName in HStack { Image(nsImage: myColorSwatches[colorName]!) Text(colorName) } } } And just as a reminder in case anybody else wants to do this, I have a color set defined in my Assets.xcassets for each named color.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jun ’21
Reply to Observe a tree of Core Data relationships?
Yes, there was an option I missed. NSTreeController seems to handle this really well, with a few small quirks. I had to add a 'rules' property to my rule. Simple extension: extension Rule { @objc public var rules: NSSet? { return self.passToLayer?.rules } } Setting up the binding was a little weird, as I've never done that in code before. Wound up with roughly this: @IBOutlet var ruleViewContainer:NSView! var ruleOutlineView:NSOutlineView = NSOutlineView() private var layerToShow:Layer private var treeController:NSTreeController = NSTreeController() ... override func viewWillAppear() { ... let outlineContainer = NSScrollView(frame:ruleViewContainer.bounds) outlineContainer.autoresizingMask = [.width, .height] outlineContainer.documentView = ruleOutlineView outlineContainer.hasVerticalScroller = true outlineContainer.hasHorizontalScroller = true ruleViewContainer.addSubview(outlineContainer) ruleOutlineView.usesAlternatingRowBackgroundColors = true ruleOutlineView.usesAutomaticRowHeights = true ruleOutlineView.delegate = self ruleOutlineView.dataSource = self ruleOutlineView.doubleAction = #selector(self.doubleClick) ruleOutlineView.target = self treeController.childrenKeyPath = "rules" treeController.bind(NSBindingName.content, to: layerToShow, withKeyPath: "rules", options: nil) ruleOutlineView.bind(NSBindingName.content, to: treeController, withKeyPath: "arrangedObjects", options: nil) } Now all the items in the NSOutlineView are of type NSTreeNode. This broke my existing drag-and-drop and outlineView(_ outlineView:, viewFor tableColumn:, item:). Easy enough to fix. Just wrap all the references to item like this: let representedItem = (item as! NSTreeNode).representedObject Then use representedItem just like you used item before. I handle the updates in my API interaction object, which then updates my Core Data store if the server confirms the attempted change was successful. The UI then updates. I still have a few weird glitches. Moved objects are sometimes out of order. That should be much easier to figure out, though.
Replies
Boosts
Views
Activity
Aug ’21
Reply to Color swatches in SwiftUI picker?
Figured it out. I used a modified version of this NSImage+TintColor extension to create a swatch dictionary: let namedColors:[String] = [ "aquamarine", "black", "blue", ... } let myColorSwatches:[String:NSImage] = { (colorNames:[String]) -> [String:NSImage] in var toReturn:[String:NSImage] = [:] for colorName in colorNames { let image = NSImage(systemSymbolName: "rectangle.fill", accessibilityDescription: nil)! image.isTemplate = false image.lockFocus() NSColor(named: colorName)!.set() let imageRect = NSRect(origin: .zero, size: image.size) imageRect.fill(using: .sourceIn) image.unlockFocus() toReturn[colorName] = image } return toReturn }(namedColors) ... which I can then reference in my SwiftUI Picker: Picker("Color:", selection: pickerColor) { ForEach(namedColors, id: \.self) { colorName in HStack { Image(nsImage: myColorSwatches[colorName]!) Text(colorName) } } } And just as a reminder in case anybody else wants to do this, I have a color set defined in my Assets.xcassets for each named color.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Jun ’21