Groups keyboard shortcuts have been updated
Dismiss
See shortcuts

Table cell with a popup button in it

52 views
Skip to first unread message

Luke

unread,
Jul 16, 2024, 6:17:01 PM7/16/24
to Cappuccino & Objective-J
I have a table rigged with bindings to data in an array controller and everything is working fine as far as that goes.  However, I'd like to add an additional column that has a drop down list (popup button) to represent the data in that cell, so the user can choose between a handful of values.  

Preferably, I'd like to use binding to drive the value to the cell, but obviously have some minimum customization to have the cell view be a CPPopUpButton with the set configuration of available values and its current selected item being driven from (and driving) the bound property of the column object.  

Is it possible to have a hybrid implementation where I can discretely make this one column do the necessary custom content stuff to present, initialize and update a bound property, or will I have to switch to using datasource and delegate logic for the whole table to achieve what I want?  

I can see some examples of custom views in table cells, but seemingly for much fancier requirements and indeed using datasource/delegate.

Martin Carlberg

unread,
Jul 17, 2024, 9:36:51 AM7/17/24
to Cappuccino & Objective-J
Hello Luke,

I am not really sure I understand exactly what you want to do. But I have done some view based tableviews with custom layout for a column with just bindings and not datasource/delegate.

- Martin

--
You received this message because you are subscribed to the Google Groups "Cappuccino & Objective-J" group.
To unsubscribe from this group and stop receiving emails from it, send an email to objectivej+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/objectivej/a44e647a-47c8-4978-945d-24a63aae391an%40googlegroups.com.

Luke

unread,
Jul 18, 2024, 3:47:54 AM7/18/24
to Cappuccino & Objective-J
Thanks Martin.  I just want the cells of one column to present a CPPopUpButton with a few fixed items in it (and select the right item depending on the bound data for that column at that row/object of course).
I'd also like picking a new item in the drop down to then set the value of the bound property. 

I've experimented a bit but haven't yet found magic that works, so have put this on the back burner, but was hoping to try again soon. 

daboe01

unread,
Jul 19, 2024, 12:48:52 AM7/19/24
to Cappuccino & Objective-J
i would suggest that a cell based table could work best for you.
just set the prototype of the last column to your CPPopupButton

Luke

unread,
Jul 19, 2024, 3:02:53 AM7/19/24
to Cappuccino & Objective-J
I tried a CPPopUpButtonCell, which seemed the obvious thing, especially as my table is otherwise "cell based", but it didn't work.   I'll see if using a CPPopUpButton (control/view) will work there instead. 

daboe01

unread,
Jul 19, 2024, 10:16:31 AM7/19/24
to Cappuccino & Objective-J
nomenclature in capp is a bit confusion. we do not have cells in the sense of cocoa. for that reason, cell based tables are acutally based on views. take a look at setDataView: from CPTableColumn

Luke

unread,
Jul 22, 2024, 2:33:23 PM7/22/24
to Cappuccino & Objective-J
(TL;DR more or less in bold below)...

Thank you again.
I do have a CPPopupButton now showing in the appropriate table cell (although it seems to change the style of the adjacent CPTextView cells by its presence, but I can live with that).

What I cannot fathom, despite trying for ages, is how I get it to work with bindings (and the rest of the bindings in my table).

Previously what is now the CPPopupButton drop down cell was just a CPTextView 'cell' and all the columns in this table are bound to the various properties of a CPArrayController handling the objects to display.
That was all good.

Now, given that the drop down list in the cell is only a convenience for the user to select between three fixed choices that occur in the model property as specific strings (Subscriber, Publisher, Admin), I'm trying to get the CPPopupButton to (naturally) show the item whose display text matches the string in the model property (called "role"), and then set that same string in the model property when the user selects another item from the menu.   In this case, I do not need to actually populate the menu with items programmatically, as these are just the fixed 3 values; I have just created this fixed menu in Xcode/IB.

By my way of thinking I just need that model property to drive the selection of the menu item by a match on its display name and then push back the string of the menu item to the property when it changes.  That seems nice and symmetrical and something a single binding would cope with... but which binding(s)?

 My first thought was to leave the table column bound to the arrangedObjects.role (string), and then bind the CPPopupButton's selectedValue to the very same (the array controller's arrangedObjects.role, being a string).  At least I read that selectedValue has to do with selection based on the displayed string of the menu item, which seems to be what I want.  

I've tried various other configurations, but haven't landed upon the magic incantation.  Unfortunately, using bindings is very concise and powerful (and I love it!), but tends to be more opaque and difficult to reason about if you haven't landed on the 'correct' configuration.

It seems to me that this ought to be simple (famous last words!), so I'm pretty sure I'm just not quite finding the right configuration.  But, there's always the possibility that Cappuccino does something differently or there's a bug etc. so if you have any ideas I would be most grateful.

daboe01

unread,
Jul 23, 2024, 12:49:17 AM7/23/24
to Cappuccino & Objective-J
iirc you do not have to bind the popupbutton explicitly. just bind the table column.

Luke

unread,
Jul 23, 2024, 1:13:26 AM7/23/24
to Cappuccino & Objective-J
Well, I had the table column bound... such that if I simply replace the CPPopUpButton with a TextField in the cell (which I had there originally), I can see the expected text from the string property. 
When I put the CPPopUpButton back in place and set it up in Xcode/IB with three menu items each displaying one of the three expected strings (and indeed one being exactly the string that I see in the TextField if that is the cell view), then nothing seems to happen... or at least  I just get presented with an empty menu item (as if it doesn't match the property text, I suppose). 

Given that you think it should just work if the table column is bound, then I shall play with this some more, just in case I hadn't quite set it up properly (like misspelling the display strings in the menu items or something).  I suppose I could also try at test case in good ol' Cocoa/Objective-C and see if it behaves the way you suggest there, as I imagine it's supposed to work exactly like the Cocoa version.

daboe01

unread,
Jul 23, 2024, 1:11:30 PM7/23/24
to Cappuccino & Objective-J
try subclassing CPPopUpButton and handle popup-item-selection in setObjectValue:
if you work with integers, try to bind the column to something like selectedTag and make the tags of your popupItems match the values.

Luke

unread,
Jul 23, 2024, 5:36:19 PM7/23/24
to Cappuccino & Objective-J
Thanks for the suggestion. 

I followed your advice.  Indeed setObjectValue is called, but weirdly, it gets called with indexes (Number values) but then also the CPString that comes from the column binding to the string property. 
I haven't fathomed why, but it gets a 0 CPNumber index initially, then a 1 CPNumber index, for some reason, and then finally the (correct) CPString.  

That makes a working setObjectValue: implementation rather 'baroque' to say the least, but then I have the problem of what to do when the user selects one of the menu items in the CPPopUpButton. 
This seems to result in setObjectValue: being sent CPNumber (with the correct item index though, which is good!).  I can convert this to the menu item title easily enough, but then how do I get the row's represented object that this instance of the CPPopUpButton in order to do a -setValue:forKey: on it?  

Also, given the spurious receipt of the "1" while the control is being initialized, I don't want to be setting the model property value to this (incorrect) value, and I suspect that doing so will just cause a loop. 
As the correct string value is always sent after the initialization 'vacillation' I suppose I could make a little bit of state in the CPPopUpButton subclass to throw away the useless indexes and only listen to them once the control is 'stable' and I know that indexes will be from the user interaction. 

Sadly, though this is rather frustrating and I wonder if I just barking up the wrong tree trying to make this work with the binding system (despite most of my UI using bindings very happily and conveniently). 
Maybe I should cut my loses and convert this table to a datasource/delegate implementation.  If there's a way to get the row's represented object from inside my CPPopUpButton subclass then this might still work though. 

daboe01

unread,
Jul 24, 2024, 9:42:47 AM7/24/24
to Cappuccino & Objective-J
hi luke,
i do not remember the details, but i got it to work nicely in cappusance.
i have several apps based on this in heavy production (inhouse software in a large university hospital)
you can have a look at my code here: https://github.com/daboe01/cappusance
daniel
Reply all
Reply to author
Forward
0 new messages