Re: [MacRuby-devel] HotCocoa table_view and the doubleAction
Quoting John Shea <johnmacshea@gmail.com>:
Hi Dave,
I am actually wrestling with a similar problem.
I believe I have solved your problem, maybe you can solve mine ;-) ??
in the start method I placed: @my_table_view.setTarget(self) @my_table_view.setDoubleAction(:double)
and then later on a method:
def double NSLog ("double") end
This worked so thanks, but did have the side effect of making the single click action fail. I think this was because I was setting it up using @tableView.on_action do NSLog "got table action via on_action..." end which seems to add the action method to a proxy object and behind the scenes sets target to the proxy object. Easily fixed by @tableView.target = self @tableView.doubleAction = 'double:' @tableView.action = 'single:' and def double (sender) end def single (sender) end In actual fact I was also using the tableViewSelectionDidChange delegate so was finding out about single clicks twice.
My issue is also delegating table updates to certain methods.
I noticed that tableview.setDelegate(self) did not do anything - and then I assumed that the TableDataSource is actually handling the delegate - confirmed when I changed the numberOfRowsInTableView method to return the value 1.
I haven't had any problems using delegate methods. For example I do: @tableView.delegate = self and define a delegate method: def tableView (table, shouldEditTableColumn: c, row: r) false end as you get told which tableView is 'calling' you you can use this to do table specific actions if one object is acting as a delegate for two tableViews. More commonly the tableView is looked after by its own instance object so the setting of the delegate of the tableView will be unique for the different tableViews. If you don't get the delegate's method signature correct they it will look like the delegate isn't working.
But then I assume that I am not supposed to add my own tableView(tv, setObjectValue:anObject, forTableColumn:col, row:row) method to the HotCocoa TableDataSource file?
I don't believe so.
What happens if I have two tables in the one application with different delegated behaviour?
Use two objects - one per tableView - to customise the delegated behaviour you want, or use the table argument to the delegate method so choose the behaviour.
Am I supposed to get funky and add the different versions of the tableView methods to the data instance itself? Is there a way to override the delegate dispatch to actually go a local class?
I think this is what the setDelegate method does. Hope this helps, Dave.
or do I setActions like in the double clicked example above?
Cheers and thanks, J
Hi Dave, thanks for your answer. On Apr 1, 2009, at 14:39 , Dave Baldwin wrote:
I haven't had any problems using delegate methods. For example I do:
@tableView.delegate = self
and define a delegate method:
def tableView (table, shouldEditTableColumn: c, row: r) false end
Thats the first thing I tried - but for the tableView(table, setObjectValue .. method which was not delegated to. Unfortunately as it was the first one i tried (because i wanted to edit table fields) - that sent me on a wild goose chase trying to figure out why the delegate was not working as it was in all of my non- hotcocoa code. So thanks for pointing out that some of them are actually delegated to. For me: #works def controlTextDidChange(notification) NSLog("controlTextDidChange #{notification.object}") NSLog(@mv_table_view.selectedRow.to_s) end #works def tableView(tv, willDisplayCell:cell, forTableColumn:col, row:the_row) NSLog("willDisplayCell") end #works def tableViewSelectionDidChange(notification) NSLog("tableViewSelectionDidChange") end #is not delegated to def tableView(tv, setObjectValue:anObject, forTableColumn:col, row:row) NSLog("tableView setObject") #edit data here end #is not delegated to def numberOfRowsInTableView(tv) NSLog("numberOfRowsInTableView") 0 #test 0 end #is not delegated to def tableView(tv, objectValueForTableColumn:col, row:row) NSLog("objectValueForTableColumn") val = "richard" end I could probably do a work around with controlTextDidChange - but it seems a bit dodgy. Or another option would be to edit not within the table, but in another form. I suppose there is some simple explanation - but I am missing it for the moment. Cheers, J
You might have already figured this out, but in case it helps... Be careful not to confuse the TableView delegate with the DataSource delegate. Check out the TableView programming guide: http://developer.apple.com/documentation/Cocoa/Conceptual/TableView/TableVie... You can use two different sets of delegate messages to customize an NSTableView. The datasource delegate methods get called in order to populate the table with data. The TableView delegate methods get called in response to user-generated events. The DataSource informal protocol: http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Prot... delegate methods specific for a TableView: http://developer.apple.com/documentation/Cocoa/Conceptual/TableView/Tasks/Us... Your tableview delegate can also respond to delegate messages for NSControl and NSView (its superclasses). In your list below,
#is not delegated to def tableView(tv, setObjectValue:anObject, forTableColumn:col, row:row) NSLog("tableView setObject") #edit data here end #is not delegated to def numberOfRowsInTableView(tv) NSLog("numberOfRowsInTableView") 0 #test 0 end #is not delegated to def tableView(tv, objectValueForTableColumn:col, row:row) NSLog("objectValueForTableColumn") val = "richard" end
These methods are sent to the 'dataSource' delegate, not the 'delegate' (view delegate). In order for your dataSource delegate methods to be called, you need to either: 1. Define the methods in a separate class, and assign an instance of that class as: @tableView.dataSource = myDataSource 2. Define the methods in your TableView Controller class, set the dataSource delegate to self: @tableView.dataSource = self You _must_ set the tableView delegate in order to receive the messages, even if you have everything in one class and you just want to set them to 'self'. For simple cases, you can implement both the 'dataSource' and view 'delegate' classes in your TableView controller and set both delegates to self. For an example of this, see the FlickrDemo example app in macruby-examples dir. Also, since it was mentioned, you should be able to leave the 'target' property unset (or set it to nil). In cocoa, nil targeted actions do _not_ go into the void. Instead, they sent are passed along the responder chain so that the next appropriate control can handle the message. This is useful for when you want to the same action to be performed as a result of different inputs (i.e. menu, button or click in row, ect..). You can just define the action methods in a class that is part of the responder chain and send a nil targeted actions from your controls. There is must-listen Mac-Developer Network podcast interview with Aaron Hillegass on the Responder Chain: http://www.mac-developer-network.com/shows/podcasts/lnc/lnc009/ Brian 2009/4/1 John Shea <johnmacshea@gmail.com>:
Hi Dave, thanks for your answer.
On Apr 1, 2009, at 14:39 , Dave Baldwin wrote:
I haven't had any problems using delegate methods. For example I do: @tableView.delegate = self and define a delegate method: def tableView (table, shouldEditTableColumn: c, row: r) false end
Thats the first thing I tried - but for the tableView(table, setObjectValue .. method which was not delegated to. Unfortunately as it was the first one i tried (because i wanted to edit table fields) - that sent me on a wild goose chase trying to figure out why the delegate was not working as it was in all of my non-hotcocoa code. So thanks for pointing out that some of them are actually delegated to. For me:
#works def controlTextDidChange(notification) NSLog("controlTextDidChange #{notification.object}") NSLog(@mv_table_view.selectedRow.to_s) end
#works def tableView(tv, willDisplayCell:cell, forTableColumn:col, row:the_row) NSLog("willDisplayCell") end #works def tableViewSelectionDidChange(notification) NSLog("tableViewSelectionDidChange") end #is not delegated to def tableView(tv, setObjectValue:anObject, forTableColumn:col, row:row) NSLog("tableView setObject") #edit data here end #is not delegated to def numberOfRowsInTableView(tv) NSLog("numberOfRowsInTableView") 0 #test 0 end #is not delegated to def tableView(tv, objectValueForTableColumn:col, row:row) NSLog("objectValueForTableColumn") val = "richard" end
I could probably do a work around with controlTextDidChange - but it seems a bit dodgy. Or another option would be to edit not within the table, but in another form. I suppose there is some simple explanation - but I am missing it for the moment. Cheers, J
_______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
Thanks Brian! that cleared up all the remaining puzzles ! I must admit i just assumed that the data source and delegate were married together in some way in hotcocoa - now that you have given me a much better background it all now makes sense. And thanks for the link. Cheers, John On Apr 1, 2009, at 8:07 PM, Brian Chapados wrote:
You might have already figured this out, but in case it helps...
Be careful not to confuse the TableView delegate with the DataSource delegate. Check out the TableView programming guide: http://developer.apple.com/documentation/Cocoa/Conceptual/TableView/TableVie...
You can use two different sets of delegate messages to customize an NSTableView. The datasource delegate methods get called in order to populate the table with data. The TableView delegate methods get called in response to user-generated events.
The DataSource informal protocol: http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Prot... /apple_ref/occ/cat/NSTableDataSource
delegate methods specific for a TableView: http://developer.apple.com/documentation/Cocoa/Conceptual/TableView/Tasks/Us... /apple_ref/doc/uid/20000116-CJBDHFIC
Your tableview delegate can also respond to delegate messages for NSControl and NSView (its superclasses).
In your list below,
#is not delegated to def tableView(tv, setObjectValue:anObject, forTableColumn:col, row:row) NSLog("tableView setObject") #edit data here end #is not delegated to def numberOfRowsInTableView(tv) NSLog("numberOfRowsInTableView") 0 #test 0 end #is not delegated to def tableView(tv, objectValueForTableColumn:col, row:row) NSLog("objectValueForTableColumn") val = "richard" end
These methods are sent to the 'dataSource' delegate, not the 'delegate' (view delegate). In order for your dataSource delegate methods to be called, you need to either:
1. Define the methods in a separate class, and assign an instance of that class as: @tableView.dataSource = myDataSource
2. Define the methods in your TableView Controller class, set the dataSource delegate to self: @tableView.dataSource = self
You _must_ set the tableView delegate in order to receive the messages, even if you have everything in one class and you just want to set them to 'self'.
For simple cases, you can implement both the 'dataSource' and view 'delegate' classes in your TableView controller and set both delegates to self. For an example of this, see the FlickrDemo example app in macruby-examples dir.
Also, since it was mentioned, you should be able to leave the 'target' property unset (or set it to nil). In cocoa, nil targeted actions do _not_ go into the void. Instead, they sent are passed along the responder chain so that the next appropriate control can handle the message. This is useful for when you want to the same action to be performed as a result of different inputs (i.e. menu, button or click in row, ect..). You can just define the action methods in a class that is part of the responder chain and send a nil targeted actions from your controls.
There is must-listen Mac-Developer Network podcast interview with Aaron Hillegass on the Responder Chain: http://www.mac-developer-network.com/shows/podcasts/lnc/lnc009/
Brian
2009/4/1 John Shea <johnmacshea@gmail.com>:
Hi Dave, thanks for your answer.
On Apr 1, 2009, at 14:39 , Dave Baldwin wrote:
I haven't had any problems using delegate methods. For example I do: @tableView.delegate = self and define a delegate method: def tableView (table, shouldEditTableColumn: c, row: r) false end
Thats the first thing I tried - but for the tableView(table, setObjectValue .. method which was not delegated to. Unfortunately as it was the first one i tried (because i wanted to edit table fields) - that sent me on a wild goose chase trying to figure out why the delegate was not working as it was in all of my non-hotcocoa code. So thanks for pointing out that some of them are actually delegated to. For me:
#works def controlTextDidChange(notification) NSLog("controlTextDidChange #{notification.object}") NSLog(@mv_table_view.selectedRow.to_s) end
#works def tableView(tv, willDisplayCell:cell, forTableColumn:col, row:the_row) NSLog("willDisplayCell") end #works def tableViewSelectionDidChange(notification) NSLog("tableViewSelectionDidChange") end #is not delegated to def tableView(tv, setObjectValue:anObject, forTableColumn:col, row:row) NSLog("tableView setObject") #edit data here end #is not delegated to def numberOfRowsInTableView(tv) NSLog("numberOfRowsInTableView") 0 #test 0 end #is not delegated to def tableView(tv, objectValueForTableColumn:col, row:row) NSLog("objectValueForTableColumn") val = "richard" end
I could probably do a work around with controlTextDidChange - but it seems a bit dodgy. Or another option would be to edit not within the table, but in another form. I suppose there is some simple explanation - but I am missing it for the moment. Cheers, J
_______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
_______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
participants (3)
-
Brian Chapados
-
Dave Baldwin
-
John Shea