NSTextField in an NSTableView truncates Dates - macos

I have an NSTableView (View type, not Cell type) which is resulting in text with "..." at the end. When I resize the columns, the "..." doesn't go away, indicating that the size is being set somewhere else... but I'm not sure where.
Here is what the table looks like:
When I make it bigger, the text is still truncated:
If I take out the ".ByClipping", I get this:
Here is the code that makes the cell:
func tableView(tableView: NSTableView, viewForTableColumn tableColumn: NSTableColumn?, row: Int) -> NSView? {
let identifier = tableColumn!.identifier
let networkName = displayedNetworks[row]
let networkVals = model.networks[networkName]!
if let val: AnyObject = networkVals[identifier] {
var obj = tableView.makeViewWithIdentifier(identifier, owner:self)
if (obj==nil) {
// No existing cell to reuse, so make a new one
obj = NSTableCellView(frame:NSMakeRect(0,0,400,400))
obj!.identifier = identifier
}
let cellView = obj as! NSTableCellView
if let d = val as? NSDate {
let formatter = NSDateFormatter()
formatter.dateStyle = NSDateFormatterStyle.ShortStyle
formatter.timeStyle = .ShortStyle
cellView.textField!.stringValue = formatter.stringFromDate(d)+"****"
cellView.textField!.lineBreakMode = .ByClipping
}
else {
cellView.textField!.stringValue = "\(val)"
}
return cellView
}
return nil
}
Something is wrong, but I can't figure it out. I thought that resizing the column resized the contained cells. Mine aren't. This is only happening with the cells that are displaying dates. What should I do?

Example you can select you Table View Cell in IB and then click that button "Resolve Auto Layuout Issues" which is just under pop over bottom left corner and the "Add Missing Constraints".

Related

Border Doesn't Draw in NSView When inside NSTableCellView

I have three NSViews inside an NSTableCellView. Depending on the data for the row, I want to show a selected role with a border on the NSView like this:
The blue border NSView is a subclass that looks like this:
class RolePill: NSView{
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
layer?.cornerRadius = 9
layer?.borderWidth = 2
layer?.borderColor = NSColor.clear.cgColor
}
}
The role gets set initially when my table loads like this:
extension UsersVC: NSTableViewDelegate, NSTableViewDataSource{
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
let cell = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "UserCell"), owner: nil) as! UserCell
let user = users[row]
//Role
cell.setRole(role: user.role)
}
}
And my table cell, where the role gets set on load and on a button click, is set up like this:
class UserCell: NSTableCellView{
#IBOutlet weak var wrapOwner: RolePill!
#IBOutlet weak var wrapAdmin: RolePill!
#IBOutlet weak var wrapUser: RolePill!
#IBAction func clickOwner(_ sender: NSButton) {
setRole(role: "owner")
}
#IBAction func clickAdmin(_ sender: NSButton) {
setRole(role: "admin")
}
#IBAction func clickUser(_ sender: NSButton) {
setRole(role: "user")
}
func setRole(role: String){
let selectedColor = getAccentColor()
let offColor = Color(named: "BravoDark")!
let offTextColor = Color(named: "BFC0C2")
switch role{
case "owner":
wrapOwner.layer?.borderColor = selectedColor.cgColor
wrapAdmin.layer?.borderColor = offColor.cgColor
wrapUser.layer?.borderColor = offColor.cgColor
labelOwner.textColor = Color.white
labelAdmin.textColor = offTextColor
labelUser.textColor = offTextColor
case "admin":
wrapOwner.layer?.borderColor = offColor.cgColor
wrapAdmin.layer?.borderColor = selectedColor.cgColor
wrapUser.layer?.borderColor = offColor.cgColor
labelOwner.textColor = offTextColor
labelAdmin.textColor = Color.white
labelUser.textColor = offTextColor
default:
wrapOwner.layer?.borderColor = offColor.cgColor
wrapAdmin.layer?.borderColor = offColor.cgColor
wrapUser.layer?.borderColor = selectedColor.cgColor
labelOwner.textColor = offTextColor
labelAdmin.textColor = offTextColor
labelUser.textColor = Color.white
}
}
}
When the table loads initially, and anytime it refreshes (tableView.reloadData()) I lose my border and it looks like this:
As you can see, the textColor is set correctly to white. But for some reason, the border isn't set until I actually click on one of the IBAction buttons and manually trigger a change.
I suspect this is some kind of layer drawing bug where the RolePill class is redrawing every time my NSTableView reloads, but I don't know how to get it to accept the initial role state sent in tableView viewForRow.
Any idea what I'm doing wrong here? Thanks!
I was able to get this to work by setting all the NSView properties inside setRole() like this:
view.wantsLayer = true
view.layer?.cornerRadius = 11
view.layer?.borderWidth = 2
view.layer?.borderColor = getAccentColor().cgColor
label.textColor = Color.white
It seemed that the draw() method on my RolePill subclass was getting called frequently, so I couldn't set a border color in there since it doesn't know what the user's data state is.

Show popOver when right click on TableViewCell

I have a NSTableView and want to show a popOver if the User right click on a row. So i have this function:
override func rightMouseDown(theEvent: NSEvent) {
super.rightMouseDown(theEvent)
var point: NSPoint = talbeView.convertPoint(theEvent.locationInWindow, fromView: nil)
var row = tableView.rowAtPoint(point)
var rec = tableView.rectOfRow(row)
let storyboard = NSStoryboard(name: "Main", bundle: nil)
let popOverViewController = storyboard!.instantiateControllerWithIdentifier("RightMousPopOver") as! NSViewController
var cell: DocumentCellView = tableView.viewAtColumn(0, row: row, makeIfNecessary: true) as! DocumentCellView
self.presentViewController(popOverViewController, asPopoverRelativeToRect: rec, ofView: cell, preferredEdge: 2, behavior: NSPopoverBehavior.Transient)
}
But the popOver appears only if I right click on the first row. I have debug the row and its right. Also if i change the row manuelle, the popOver show on the right row, but again only if I click on the first row.
I'm little bit confused. What is wrong withe my code?
Ok i think i found the answer. tableView.rectOfRow(row) is false. cell.frame is the right way to get the NSRec

collect result of NStableView with checkboxes in Swift

I have hard time trying to collect the number of checkboxes checked inside the second column of a NStableView.
I composed a NSTableView with 2 column (via IB),
the first is named : BugColumn (it contains textfiled)
the second is named : CheckedColumn (it contains checkboxes)
Here is the code used to display strings in the first column :
var objets: NSMutableArray! = NSMutableArray()
...
extension MasterViewController: NSTableViewDataSource
{
func numberOfRowsInTableView(aTableView: NSTableView) -> Int
{
return self.objets.count
}
func tableView(tableView: NSTableView, viewForTableColumn tableColumn: NSTableColumn?, row: Int) -> NSView?
{
var cellView: NSTableCellView = tableView.makeViewWithIdentifier(tableColumn!.identifier, owner: self) as! NSTableCellView
if tableColumn!.identifier == "BugColumn"
{
cellView.textField!.stringValue = self.objets.objectAtIndex(row) as! String
}
return cellView
}
The second column is made of checkboxes appearing for each element of the first column.
I would like to know what is the corresponding text in the first column for each checkboxes enabled (checked).
I red a few exemples about NSTableView but, or they do differents things, or they are in Objective-C.
Could someone explain how to do that using swift?
Thanks

How to apply different content on the same cell identifier on UICollectionView in Swift?

Is this code make sense to you? I am trying to put different content on the same cell identifier which's triggered on collectionView:didSelectItemAtIndexPath::
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
println("bosen kelima")
if (collectionView == self.filterCollectionView) {//here
println("First Content")
let cell = self.filterCollectionView.dequeueReusableCellWithReuseIdentifier("FILTER_CELL", forIndexPath: indexPath) as! FilterThumbnailCell
var filterThumbnail = self.filterThumbnails![indexPath.row] // this one through bottom of this function will be deleted and moved to "didSelectItemAtIndexPath"
var filterThumbnailTwo = self.secondFilterThumbnails![indexPath.row]
cell.filterTitle.text = filterThumbnail.filterName
//Lazy Loading
if filterThumbnail.filteredThumbnail != nil {
cell.imageView.image = filterThumbnail.filteredThumbnail
}
else {
cell.imageView.image = filterThumbnail.originalThumbnail
//filterThumbnail is a class instance
filterThumbnail.generateThumbnail({ (image) -> Void in
if let cell = collectionView.cellForItemAtIndexPath(indexPath) as? FilterThumbnailCell {
cell.imageView.image = image
}
})
}
if filterThumbnailTwo.filteredThumbnail != nil {
cell.imageView.image = filterThumbnailTwo.filteredThumbnail
}
else {
cell.imageView.image = filterThumbnailTwo.originalThumbnail
//filterThumbnail is a class instance
filterThumbnailTwo.generateThumbnail({ (image) -> Void in
if let cell = collectionView.cellForItemAtIndexPath(indexPath) as? FilterThumbnailCell {
cell.imageView.image = image
}
})
}
return cell
}
}
if it doesn't make sense, can you give me solution? I've been looking the solution for almost a week but still no clue
What different content?
If you have the same Cell type with different states, you will need a Bool (2 states) or an enum for 2 or more states.
You then check the state of the cell and do what you need to. You also need to update the cell state from the correct object as needed.

Updated NSTableCellView.textField NOT updated in table display.

I have a feeling this table cell display problem has a simple answer but, I clearly need greater wisdom than mine to find it.
Here's my textbook controller, delegate and datasource class for the table and the enclosing view ...
import Cocoa
class Table8020ViewController: NSViewController, NSTableViewDelegate, NSTableViewDataSource {
var tokenText: [String] = ["alpha", "beta", "gamma", "delta", "epsilon", "zeta"]
override func viewDidLoad() {
super.viewDidLoad()
}
func numberOfRowsInTableView(aTableView: NSTableView) -> Int {
println("numberOfRowsInTableView = \(tokenText.count)")
return tokenText.count
}
func tableView(aTableView: NSTableView, objectValueForTableColumn aTableColumn: NSTableColumn?, row rowIndex: Int) -> AnyObject? {
var result = aTableView.makeViewWithIdentifier(aTableColumn!.identifier, owner: self) as! NSTableCellView
println("textField in = \(result.textField!.stringValue)")
result.textField!.stringValue = tokenText[rowIndex]
println("textField out = \(result.textField!.stringValue)")
return result
}
}
I log the updates to the .textField which seems to work ok.
numberOfRowsInTableView = 6
textField in = Table View Cell
textField out = alpha
textField in = Table View Cell
textField out = beta
textField in = Table View Cell
textField out = gamma
textField in = Table View Cell
textField out = delta
textField in = Table View Cell
textField out = epsilon
textField in = Table View Cell
textField out = zeta
But the actual table display retains the original interface builder values! 'Table View Cell' Something mysterious appears to be happening after after the 'return result'.
I'm using the latest Xcode Version 6.3 (6D570) with Swift V1.2
You're making a couple of mistakes.
Firstly you're returning the wrong kind of value from tableView:objectValueForTableColumn:row. This method isn't requesting a view instance, it's requesting the object that your view instance will be representing. In other words it wants to know what model object the view will be displaying. In each case your model object is very simple - it's one of the strings in the tokenText array.
func tableView(tableView: NSTableView,
objectValueForTableColumn tableColumn: NSTableColumn?,
row: Int) -> AnyObject? {
return tokenText[row]
}
Secondly you've failed to implement tableView:viewForTableColumn:row:. This is where you create a view for each cell in your table and tell that view which bits of the model object you want to display. In each case your model object is just a string, so you essentially tell the view to display the entire model object in its textField:
func tableView(tableView: NSTableView,
viewForTableColumn tableColumn: NSTableColumn?,
row: Int) -> NSView? {
var view = tableView.makeViewWithIdentifier(tableColumn!.identifier,
owner: self) as! NSTableCellView
view.textField!.stringValue = tokenText[row]
return view
}

Resources