Re: Leopard NSTableView Cell and single click editing

  • >>> [...]
    >>
    >> There seems to be some inconsistency in how this works in
    >> NSTableView, depending on whether or not the cell you click is in a
    >> selected (highlighted) row. (I have a database application with an
    >> all-text table view.)
    >>
    >> If you single-click on a cell in an unselected row, that cell
    >> becomes active, with the insertion point at the beginning of the
    >> text. If you double-click, or click and hold past the double-click
    >> interval, the same thing happens.
    >>
    >> However, if you single-click in a different cell of a selected row,
    >> the clicked cell does not become active, although the previously
    >> active cell does become inactive. Once all cells in the row are
    >> inactive, single-clicking causes the clicked cell to become active,
    >> but with all of the cell text selected.
    >>
    >> If you double-click (or click and hold past the double-click
    >> interval) on a different cell in the same row, it's the same as if
    >> you had performed two single clicks in a row; the current cell
    >> becomes inactive, then the clicked cell becomes active with all its
    >> text selected.
    >
    > Are these things only happening in your app? Can you try them with the
    > DragNDropOutlineView demo app? I don't see these things happening
    > there.

    DragNDropOutlineView doesn't seem to have multiple selectable columns,
    so I couldn't figure out how to compare it to mine. (But see below.)

    > Leopard: Single clicking on *text* will begin editing if: that row was
    > the only row selected.
    > Tiger: Single clicking on the cell will begin editing if: that row was
    > the only row selected.
    >
    > If the row wasn't selected, single clicking will first select it. You
    > have to then wait at least until the double click delay to avoid
    > sending the doubleAction (if set -- if not set, then it doesn't
    > matter).
    >
    > If more than one row was selected, and you single click on a row, that
    > single row becomes selected after the double click delay; this allows
    > the double click action to be applied to the entire selection (Finder
    > also works this way).
    >
    >> Before Leopard, the behavior was the same in both selected and
    >> unselected rows.
    >
    > Before Leopard, the last item was never a factor; single clicking a
    > row would *always* immediately select just that row, and not allow you
    > to apply a "doubleAction" to a group of selected rows. This was an
    > explicit bug fix, and hopefully people will see the benefit that it
    > adds to applications.
    >
    >> The clicked cell became active and a single click resulted in the
    >> insertion point being at the beginning of the text, while a double-
    >> click resulted in all of the cell text being selected.
    >
    > Before Leopard, a double click was required to begin editing. The
    > first click selected that row, and the second click was the double
    > click that began editing.
    >
    >> Is any of this inconsistency likely to be due to anything I'm doing
    >> in my NSTableView delegate methods? Or, is it strictly by design in
    >> Leopard?
    >
    > Possibly; the problems you are listing sound different than what I've
    > seen before. It is strange that single clicking on a non-selected row
    > would begin editing. It must first be selected before editing can
    > begin. So, something strange is happening in your app (maybe you
    > manually begin editing at some point?)

    (Frankly, I haven't had to mess with this part of my code in well over
    a year, so I had to refresh my memory of the details. It's reasonably
    complex, but worked fine until y'all fixed all those bugs...)

    Digging around in my app, I see that I have an IBAction, -
    tableViewHit:, that calls -editColumn:row:withEvent:select: if -
    tableView:shouldEditTableColumn:row: returns YES--which it normally
    does.

    Under Tiger, -tableViewHit: gets called whenever the table is clicked,
    regardless of which row is clicked.

    It appears that, under Leopard, it doesn't get called if -
    tableView:shouldEditTableColumn:row: returns YES and the active row is
    clicked. However, it does get called if some other row is clicked.

    >> What do you recommend as the best approach for getting cells in a
    >> Tiger-compatible database application to respond in a consistent
    >> way, regardless of whether the clicked cell is in a selected row or
    >> not? I'd prefer the Tiger behavior, for a variety of reasons.
    >
    > Make the delegate method"tableView:shouldEditTableColumn:.." always
    > return NO. This refuses normal editing behavior. Then, in the
    > doubleAction, if the clickedRow/clickedColumn's are valid, begin
    > editing manually by calling editColumn:row:...

    Under Leopard, setting -tableView:shouldEditTableColumn:row: to always
    return NO causes -tableViewHit to be called every time the table is
    clicked, regardless of whether the clicked row is active or not. So
    I've done that.

    I also set a doubleAction function.

    The problem with this is that double-clicking produces the same effect
    as single-clicking, leaving the field text unselected.

    If my -tableViewHit calls -editColumn:row:..., then the the
    doubleAction function never gets called. If I comment it out, then the
    doubleAction function does get called.

    Of course, that screws up a lot of how things work in my app, as the -
    tableViewHit routine performs or calls a variety of functions that
    don't work if -editColumn:row:... is not called at the right time in
    the flow.

    I thought that maybe I should be doing something with -setAction,
    instead, but in that case, double-clicking again fails to activate the
    doubleAction routine. The action routine is called both for single-
    clicks and for double-clicks. It looks like action and doubleAction
    can't coexist--unless I'm missing some subtlety.

    I definitely don't want my users to have to double-click to get at the
    contents of a field. For one thing, if it causes the contents to be
    selected, then if it contains a link, that link won't be clickable,
    until the user clicks for a third time to deselect the contents. (This
    non-clickability of highlighted text also seems to be new with Leopard.)

    This means that a user will require four mouse clicks to access a
    link, vs. two clicks under Tiger. That's ain't gonna fly. We'd already
    had complaints about requiring two clicks.

    I think that, for now, I'm just going with single- and double-clicks
    acting the same: activating the field and not selecting the text. If
    the user needs the text highlighted, there's always command-A. It
    seems to me that this will be more in line with our users'
    expectations and past experience.

    Since everything is fine in Tiger, I now test for the OS and -
    tableView:shouldEditTableColumn:.. returns NO under Leopard, but
    returns the result of a couple of tests under Tiger.

    Other than the non-functioning double-clicks, the app now works about
    the same under Leopard as under Tiger.

    > Let me know if this works well for you. Hopefully it is easy to do.

    Another issue that I've just noticed is that if -
    tableView:shouldEditTableColumn:row: returns NO, then tabbing no
    longer moves to the next column. Instead, it just jumps to the next
    NSTextView, as if there was only a single column. And backtabbing
    simply deselects the current cell.

    Is there a way to avoid that without having to handle tabs myself?
    (Fortunately, my previous rev added new command keys to replace the
    loss of traditional database tab and return functions in tables under
    Leopard, so I guess we can live without tabs if we have to.)

    Thanks,
    Mike Wright
    http://www.idata3.com/
  • >>> cted.
    >>
    >> Are these things only happening in your app? Can you try them with
    >> the
    >> DragNDropOutlineView demo app? I don't see these things happening
    >> there.
    >
    > DragNDropOutlineView doesn't seem to have multiple selectable
    > columns, so I couldn't figure out how to compare it to mine. (But
    > see below.)

    You mean multiple selectable rows, or columns? I'm guessing rows, and
    I thought by default it allowed that. However, based on your lower
    comments, it is irrelevant.
    >>
    >> Possibly; the problems you are listing sound different than what I've
    >> seen before. It is strange that single clicking on a non-selected row
    >> would begin editing. It must first be selected before editing can
    >> begin. So, something strange is happening in your app (maybe you
    >> manually begin editing at some point?)
    >
    > (Frankly, I haven't had to mess with this part of my code in well
    > over a year, so I had to refresh my memory of the details. It's
    > reasonably complex, but worked fine until y'all fixed all those
    > bugs...)
    >
    > Digging around in my app, I see that I have an IBAction, -
    > tableViewHit:, that calls -editColumn:row:withEvent:select: if -
    > tableView:shouldEditTableColumn:row: returns YES--which it normally
    > does.
    >
    > Under Tiger, -tableViewHit: gets called whenever the table is
    > clicked, regardless of which row is clicked.
    >
    > It appears that, under Leopard, it doesn't get called if -
    > tableView:shouldEditTableColumn:row: returns YES and the active row
    > is clicked. However, it does get called if some other row is clicked.

    Ah; so you are manually starting editing via the single click action;
    I'm surprised this hasn't conflicted with NSTableViews starting of
    editing before.

    >
    >>> What do you recommend as the best approach for getting cells in a
    >>> Tiger-compatible database application to respond in a consistent
    >>> way, regardless of whether the clicked cell is in a selected row or
    >>> not? I'd prefer the Tiger behavior, for a variety of reasons.
    >>
    >> Make the delegate method"tableView:shouldEditTableColumn:.." always
    >> return NO. This refuses normal editing behavior. Then, in the
    >> doubleAction, if the clickedRow/clickedColumn's are valid, begin
    >> editing manually by calling editColumn:row:...
    >
    > Under Leopard, setting -tableView:shouldEditTableColumn:row: to
    > always return NO causes -tableViewHit to be called every time the
    > table is clicked, regardless of whether the clicked row is active or
    > not. So I've done that.

    This should also happen under Tiger; the 'action' is always sent when
    the user clicks on something in the tableview, regardless of what it
    clicked on.

    >
    > I also set a doubleAction function.
    >
    > The problem with this is that double-clicking produces the same
    > effect as single-clicking, leaving the field text unselected.

    You mean, it doesn't start editing? Or it does start editing?

    >
    > If my -tableViewHit calls -editColumn:row:..., then the the
    > doubleAction function never gets called. If I comment it out, then
    > the doubleAction function does get called.

    You should set the doubleAction to something, say
    "tableViewDoubleAction:", and in your implementation check to see if
    the clickedRow/clickedColumn are valid, and if they are, then call -
    editColumn:row:...

    What you are seeing is expected; if the single click 'action' starts
    editing, then the second click is sent to that edited cell, and not to
    your table itself. Hence, you don't get a doubleAction.

    >
    > Of course, that screws up a lot of how things work in my app, as the
    > -tableViewHit routine performs or calls a variety of functions that
    > don't work if -editColumn:row:... is not called at the right time in
    > the flow.

    It sounds like you are expecting -tableViewHit (the 'action') to be
    called on single clicking and double clicking, and sometimes you want
    to begin editing and sometimes you don't. Exactly what things do you
    need to do, and based on what user action. I'm getting confused to
    exactly what your goal is, but if you help me understand, I may be
    able to provide some better insight. For instance: You need X to
    happen when the user single clicks. You need Y to happen when the user
    double clicks. You want to start editing when Z happens.

    >
    > I thought that maybe I should be doing something with -setAction,
    > instead, but in that case, double-clicking again fails to activate
    > the doubleAction routine. The action routine is called both for
    > single-clicks and for double-clicks. It looks like action and
    > doubleAction can't coexist--unless I'm missing some subtlety.

    It can co-exist, and this was one of the main reasons we changed this
    for Leopard. One can have a single 'action' perform editing, and the
    double action do something else.

    >
    > I definitely don't want my users to have to double-click to get at
    > the contents of a field. For one thing, if it causes the contents to
    > be selected, then if it contains a link, that link won't be
    > clickable, until the user clicks for a third time to deselect the
    > contents. (This non-clickability of highlighted text also seems to
    > be new with Leopard.)
    >
    > This means that a user will require four mouse clicks to access a
    > link, vs. two clicks under Tiger. That's ain't gonna fly. We'd
    > already had complaints about requiring two clicks.

    Can you post a screen shot of your UI or app somewhere so I can see
    what you are attempting to do? Part of your problem may be solved by
    calling 'selectWithFrame:' vs 'editWithFrame:' in the custom cell
    subclass.

    >
    > I think that, for now, I'm just going with single- and double-clicks
    > acting the same: activating the field and not selecting the text. If
    > the user needs the text highlighted, there's always command-A. It
    > seems to me that this will be more in line with our users'
    > expectations and past experience.
    >
    > Since everything is fine in Tiger, I now test for the OS and -
    > tableView:shouldEditTableColumn:.. returns NO under Leopard, but
    > returns the result of a couple of tests under Tiger.
    >
    > Other than the non-functioning double-clicks, the app now works
    > about the same under Leopard as under Tiger.
    >
    >> Let me know if this works well for you. Hopefully it is easy to do.
    >
    > Another issue that I've just noticed is that if -
    > tableView:shouldEditTableColumn:row: returns NO, then tabbing no
    > longer moves to the next column. Instead, it just jumps to the next
    > NSTextView, as if there was only a single column. And backtabbing
    > simply deselects the current cell.'

    Yes; unfortunately, the tabbing logic has to key off of something, and
    that delegate method is one of the things it uses.

    >
    > Is there a way to avoid that without having to handle tabs myself?
    > (Fortunately, my previous rev added new command keys to replace the
    > loss of traditional database tab and return functions in tables
    > under Leopard, so I guess we can live without tabs if we have to.)
    >

    Well, the only way is to return YES from the above delegate
    method...but that may conflict with other things.

    -corbin
  • On Dec 5, 2007, at 13:04 , Corbin Dunn wrote:

    >>>> [...]
    >>>> What do you recommend as the best approach for getting cells in a
    >>>> Tiger-compatible database application to respond in a consistent
    >>>> way, regardless of whether the clicked cell is in a selected row or
    >>>> not? I'd prefer the Tiger behavior, for a variety of reasons.
    >>>
    >>> Make the delegate method"tableView:shouldEditTableColumn:.." always
    >>> return NO. This refuses normal editing behavior. Then, in the
    >>> doubleAction, if the clickedRow/clickedColumn's are valid, begin
    >>> editing manually by calling editColumn:row:...
    >>
    >> Under Leopard, setting -tableView:shouldEditTableColumn:row: to
    >> always return NO causes -tableViewHit to be called every time the
    >> table is clicked, regardless of whether the clicked row is active
    >> or not. So I've done that.
    >
    > This should also happen under Tiger; the 'action' is always sent
    > when the user clicks on something in the tableview, regardless of
    > what it clicked on.
    >
    >> I also set a doubleAction function.
    >>
    >> The problem with this is that double-clicking produces the same
    >> effect as single-clicking, leaving the field text unselected.
    >
    > You mean, it doesn't start editing? Or it does start editing?

    It starts editing, placing the insertion point at the beginning of the
    text. (Again, this happens when -tableView:shouldEditTableColumn:row:
    is set to always return NO.)

    I'd like double-clicking to cause the cell text to be selected, but
    I've spent most of the day disabling various routines and writing new
    ones, with -tableView:shouldEditTableColumn:row: returning both YES
    and NO, and this is the best I've come up with.

    From my various experiments, it appears that -
    tableView:shouldEditTableColumn:row: doesn't even get called when you
    first click in an unselected row. Instead, the clicked row becomes
    selected and is only then eligible to have its cells edited. Is that
    correct?

    I suppose I should write a little sample app that just puts a database-
    style table in a window and fills it with canned data in order to test
    a pure version, without any possible side effects from my other
    routines. There doesn't seem to be such example code on my machine. Is
    there any on the Web? (Because I'm lazy, and I'd rather be playing my
    new banjo.)

    >> If my -tableViewHit calls -editColumn:row:..., then the the
    >> doubleAction function never gets called. If I comment it out, then
    >> the doubleAction function does get called.
    >
    > You should set the doubleAction to something, say
    > "tableViewDoubleAction:", and in your implementation check to see if
    > the clickedRow/clickedColumn are valid, and if they are, then call -
    > editColumn:row:...

    That's what I did. I set the doubleAction to a routine called -
    doubleClicked, but that routine never gets called.

    > What you are seeing is expected; if the single click 'action' starts
    > editing, then the second click is sent to that edited cell, and not
    > to your table itself. Hence, you don't get a doubleAction.
    >
    >> Of course, that screws up a lot of how things work in my app, as
    >> the -tableViewHit routine performs or calls a variety of functions
    >> that don't work if -editColumn:row:... is not called at the right
    >> time in the flow.
    >
    > It sounds like you are expecting -tableViewHit (the 'action') to be
    > called on single clicking and double clicking, and sometimes you
    > want to begin editing and sometimes you don't. Exactly what things
    > do you need to do, and based on what user action. I'm getting
    > confused to exactly what your goal is, but if you help me
    > understand, I may be able to provide some better insight. For
    > instance: You need X to happen when the user single clicks. You need
    > Y to happen when the user double clicks. You want to start editing
    > when Z happens.

    I want editing to start for both single and double clicks. In the case
    of a single click, I want to get an insertion point at the beginning
    of the cell text. In the case of a double click, I want all of the
    cell text to be selected.

    This is how my app works under Tiger. Whether the clicked cell is in
    the currently active row on not doesn't affect the way it works.

    >> I thought that maybe I should be doing something with -setAction,
    >> instead, but in that case, double-clicking again fails to activate
    >> the doubleAction routine. The action routine is called both for
    >> single-clicks and for double-clicks. It looks like action and
    >> doubleAction can't coexist--unless I'm missing some subtlety.
    >
    > It can co-exist, and this was one of the main reasons we changed
    > this for Leopard. One can have a single 'action' perform editing,
    > and the double action do something else.

    But they can't both start editing, right? Because the first click of a
    double click will deselect the current cell and select the current row
    without waiting to see if another click follows within the double-
    click interval, as you say above?

    >> I definitely don't want my users to have to double-click to get at
    >> the contents of a field. For one thing, if it causes the contents
    >> to be selected, then if it contains a link, that link won't be
    >> clickable, until the user clicks for a third time to deselect the
    >> contents. (This non-clickability of highlighted text also seems to
    >> be new with Leopard.)
    >>
    >> This means that a user will require four mouse clicks to access a
    >> link, vs. two clicks under Tiger. That's ain't gonna fly. We'd
    >> already had complaints about requiring two clicks.
    >
    > Can you post a screen shot of your UI or app somewhere so I can see
    > what you are attempting to do? Part of your problem may be solved by
    > calling 'selectWithFrame:' vs 'editWithFrame:' in the custom cell
    > subclass.

    I've put up a couple of screen shots, with comments, here: <http://www.idata3.com/id3tables.html>

    If you'd like to see the difference in behavior under Tiger and
    Leopard for yourself, you can download the current version (which will
    run without a serial number for 30 days) here: < http://www.idata3.com/idata3012.zip
    > . It includes a folder that contains a couple of sample datafiles.
    Sample Field Datafile is the one I used for my screen shots.

    Switch View, under the View menu, will show a single-record view with
    two columns. Clicking the leftmost (field name) column will select the
    corresponding field with the text highlighted. Clicking in a field
    will select the cell with the insertion point at the beginning of the
    text. This is close enough to the behavior under Tiger that I don't
    need to modify it.

    >> I think that, for now, I'm just going with single- and double-
    >> clicks acting the same: activating the field and not selecting the
    >> text. If the user needs the text highlighted, there's always
    >> command-A. It seems to me that this will be more in line with our
    >> users' expectations and past experience.
    >>
    >> Since everything is fine in Tiger, I now test for the OS and -
    >> tableView:shouldEditTableColumn:.. returns NO under Leopard, but
    >> returns the result of a couple of tests under Tiger.
    >>
    >> Other than the non-functioning double-clicks, the app now works
    >> about the same under Leopard as under Tiger.
    >>
    >>> Let me know if this works well for you. Hopefully it is easy to do.
    >>
    >> Another issue that I've just noticed is that if -
    >> tableView:shouldEditTableColumn:row: returns NO, then tabbing no
    >> longer moves to the next column. Instead, it just jumps to the next
    >> NSTextView, as if there was only a single column. And backtabbing
    >> simply deselects the current cell.'
    >
    > Yes; unfortunately, the tabbing logic has to key off of something,
    > and that delegate method is one of the things it uses.
    >
    >> Is there a way to avoid that without having to handle tabs myself?
    >> (Fortunately, my previous rev added new command keys to replace the
    >> loss of traditional database tab and return functions in tables
    >> under Leopard, so I guess we can live without tabs if we have to.)
    >
    > Well, the only way is to return YES from the above delegate
    > method...but that may conflict with other things.

    Thanks,
    Mike Wright
    http://www.idata3.com/
previous month december 2007 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