NSCell subclass with custom binding

  • Hi all,

    I've used bindings a great deal including custom classes that expose
    their own bindings but this is the first time I've tried to expose a
    custom binding for an NSActionCell subclass that would work in an
    NSTableView. Here is the situation:

    NSActionCell subclass exposes a custom binding and implements the
    necessary methods for binds and observation of changes.

    NSTableView with two columns, the first column's value is bound to
    an NSArrayController backed by an NSMutableArray with Controller Key
    arrangedObjects and Model Key Path name. That works fine of course.
    The second column has my NSActionCell set as it's dataCell. This is
    where the difficultly begins.

    Since the binding is custom the NSTableColumn cannot be bound to it
    because of course it knows nothing about it. I'm not sure if there is
    a way to get NSTableColumns to know about new bindings
    programmatically. There is also no point in binding the NSActionCell
    subclass itself because it only wants a single value and binding to
    arrangedObjects.bindingname of the NSArrayController would result in
    an array. I don't know exactly what NSTableColumn does to correctly
    provide the NSCell with its value but it seems like it probably gets
    the value via the binding and iterates over the values for the
    visible cells.

    Anyway, my questions are: Is there a way to get NSTableColumn to
    know about custom bindings either programmatically or through IB? Or,
    is there some way to establish the binding with the NSActionCell that
    would work?

    I know mmalc has pointed to his ClockControl example but the custom
    binding for that is in the NSControl subclass and it doesn't seem
    like I should need an NSControl if I am only interested in an
    NSActionCell that can be placed in a table. His ReadMe also says "
    Note that establishing a binding is tricky.  You must ensure that the
    correct binder is used.  This is most easily achieved if you
    establish the binding programatically." about using the clock control
    in a table view. That is a bit cryptic to me.

    Thanks for any help,

    Stephan Cleaves
  • On Oct 21, 2006, at 8:40 AM, Stephan Cleaves wrote:

    > Since the binding is custom the NSTableColumn cannot be bound to it
    > because of course it knows nothing about it. I'm not sure if there
    > is a way to get NSTableColumns to know about new bindings
    > programmatically.

    You can't do it graphically, but you can usually do it
    programmatically using the KVB protocol methods. In fact, you can
    even bind things that aren't explicitly exposed (at least sometimes).

    > I don't know exactly what NSTableColumn does to correctly provide
    > the NSCell with its value but it seems like it probably gets the
    > value via the binding and iterates over the values for the visible
    > cells.

    The table column will just use whatever keypath you give it. So if
    you bind its 'value' property to:

    SomeArrayController.arrangedObjects.name:

    It will call 'name' or 'setName' on each model object. The result of
    'name' on the model object will be set as the object value for the
    cell that is currently being displayed.

    I haven't done exactly what you're describing, but I think if your
    subclass does the right thing in -value and -setValue (and by "right
    thing," I mean properly update its display), then I *think* you
    should be set.

    > Anyway, my questions are: Is there a way to get NSTableColumn to
    > know about custom bindings either programmatically or through IB

    It should be something of the flavor:

    [column
        bind:@"value"
        toObject:arrayController
        withKeyPath:@"arrangedObjects.someProperty"
        options:nil];

    You'd probably make something method called -setupCustomBindings and
    call that in -awakeFromNib.

    > There is also no point in binding the NSActionCell subclass itself
    > because it only wants a single value and binding to
    > arrangedObjects.bindingname of the NSArrayController would result
    > in an array.

    You could also possibly get away with dropping an NSButtonCell in
    your table in IB (since it's an action cell), setup the bindings in
    IB as well, then swap in your custom data cell at runtime. If that
    works, it would be a simpler solution since you don't have to setup
    bindings programmatically.

    I did something like this, but with an NSImageCell subclass instead:
    http://theocacao.com/document.page/196

        - Scott
  • On Oct 21, 2006, at 5:49 PM, Scott Stevenson wrote:

    >
    >> I don't know exactly what NSTableColumn does to correctly provide
    >> the NSCell with its value but it seems like it probably gets the
    >> value via the binding and iterates over the values for the visible
    >> cells.
    >
    > The table column will just use whatever keypath you give it. So if
    > you bind its 'value' property to:
    >
    > SomeArrayController.arrangedObjects.name:
    >
    > It will call 'name' or 'setName' on each model object. The result
    > of 'name' on the model object will be set as the object value for
    > the cell that is currently being displayed.
    >
    > I haven't done exactly what you're describing, but I think if your
    > subclass does the right thing in -value and -setValue (and by
    > "right thing," I mean properly update its display), then I *think*
    > you should be set.
    >
    >

    Thanks for the reply. It is true that I could bind to value and be
    fine but if I wanted more than one binding to my NSActionCell
    subclass that wouldn't help (unless of course I was using a compound
    object for the value, which may in the end be what I have to do.) I
    realize my original example didn't state I needed more than one binding.

    >> Anyway, my questions are: Is there a way to get NSTableColumn to
    >> know about custom bindings either programmatically or through IB
    >
    > It should be something of the flavor:
    >
    > [column
    > bind:@"value"
    > toObject:arrayController
    > withKeyPath:@"arrangedObjects.someProperty"
    > options:nil];
    >
    > You'd probably make something method called -setupCustomBindings
    > and call that in -awakeFromNib.
    >

    True, though the above could be done in IB. But for my own custom
    bindings I would need to do something along those lines. What I would
    like to do is bind to my custom bindings, let's call them value2 and
    value3 to arrangedObjects.property2 and arrangedObjects.property3
    respectively. It would seem this is possible because the
    NSLevelIndicatorCell has 3 bindings, the generic value accompanied by
    minValue and maxValue. I guess the question is, how can I create the
    equivalent of minValue and maxValue for my NSActionCell subclass?

    If it turns out that having custom bindings for NSCell subclasses
    that are used in NSTableViews is not possible I can always fall back
    on the compound object bound to the cell's value. I don't believe
    this would be a problem because the cell in question is not editing
    the data, just reacting to value changes. Utilizing
    setKeys:triggerChangeNotificationsForDependentKey: should make it
    relatively painless for the compound object notifications to go out.

    Stephan
  • Wow, haven't been on this list in years.

    So I was looking into this issue (see below), which was raised a few
    times last year, because I need to do the same thing, but I have come
    to the realization (somewhat obvious, in retrospect), that the only
    way to get NSTableColumn to support more bindings (for cells with more
    than one attribute to which you wish to bind) is to subclass
    NSTableColumn. Cells don't support bindings -- controls do.

    NSTableColumn does support more than just the "value" binding -- if
    you use a popup cell, for example, you get 'content" and "content
    values" as well (actually I'm not 100% on the exact names). It's this
    kind of behaviour that would be desired, and especially in IB, but
    that would seem to require a subclass and an IB plug-in (for IB3).

    It is not immediately obvious to me how a class can "un"-expose
    bindings, as table columns seem to do when you change the cell class
    from a popup back to a text field or something with only the Value
    binding.

    While I'm on the topic, I was wondering if there is a way to get
    pop-up cells in table columns using the value binding to respect their
    menu outlet and select the value in the menu which matches the value
    in the binding. I wish that there was a binding for selected index,
    like there is in a pop up control. But I'm not holding my breath.

    -b-

    On Oct 22, 2006 11:33 AM, Stephan Cleaves <stephan...> wrote:
    >
    > On Oct 21, 2006, at 5:49 PM, Scott Stevenson wrote:
    >
    >>
    >>> I don't know exactly what NSTableColumn does to correctly provide
    >>> the NSCell with its value but it seems like it probably gets the
    >>> value via the binding and iterates over the values for the visible
    >>> cells.
    >>
    >> The table column will just use whatever keypath you give it. So if
    >> you bind its 'value' property to:
    >>
    >> SomeArrayController.arrangedObjects.name:
    >>
    >> It will call 'name' or 'setName' on each model object. The result
    >> of 'name' on the model object will be set as the object value for
    >> the cell that is currently being displayed.
    >>
    >> I haven't done exactly what you're describing, but I think if your
    >> subclass does the right thing in -value and -setValue (and by
    >> "right thing," I mean properly update its display), then I *think*
    >> you should be set.
    >>
    >>
    >
    > Thanks for the reply. It is true that I could bind to value and be
    > fine but if I wanted more than one binding to my NSActionCell
    > subclass that wouldn't help (unless of course I was using a compound
    > object for the value, which may in the end be what I have to do.) I
    > realize my original example didn't state I needed more than one binding.
    >
    >>> Anyway, my questions are: Is there a way to get NSTableColumn to
    >>> know about custom bindings either programmatically or through IB
    >>
    >> It should be something of the flavor:
    >>
    >> [column
    >> bind:@"value"
    >> toObject:arrayController
    >> withKeyPath:@"arrangedObjects.someProperty"
    >> options:nil];
    >>
    >> You'd probably make something method called -setupCustomBindings
    >> and call that in -awakeFromNib.
    >>
    >
    > True, though the above could be done in IB. But for my own custom
    > bindings I would need to do something along those lines. What I would
    > like to do is bind to my custom bindings, let's call them value2 and
    > value3 to arrangedObjects.property2 and arrangedObjects.property3
    > respectively. It would seem this is possible because the
    > NSLevelIndicatorCell has 3 bindings, the generic value accompanied by
    > minValue and maxValue. I guess the question is, how can I create the
    > equivalent of minValue and maxValue for my NSActionCell subclass?
    >
    > If it turns out that having custom bindings for NSCell subclasses
    > that are used in NSTableViews is not possible I can always fall back
    > on the compound object bound to the cell's value. I don't believe
    > this would be a problem because the cell in question is not editing
    > the data, just reacting to value changes. Utilizing
    > setKeys:triggerChangeNotificationsForDependentKey: should make it
    > relatively painless for the compound object notifications to go out.
    >
    > Stephan
    >
    >
    > _______________________________________________
    > Do not post admin requests to the list. They will be ignored.
    > Cocoa-dev mailing list      (<Cocoa-dev...>)
    > Help/Unsubscribe/Update your Subscription:
    > http://lists.apple.com/mailman/options/cocoa-dev/<bgulanowski...>
    >
    > This email sent to <bgulanowski...>
    >

    --
    Brent Gulanowski
previous month october 2006 next month
MTWTFSS
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31          
Go to today