But it appears to me that the code could be cleaned up and
simplified quite a bit if everyone agrees with my assertion that a
view should only have one (or zero) nextKeyView. To begin with, the
_nextKeyView ivar could be turned into a direct pointer to the next
key view rather than a GSIArray. Also, the code is not well
encapsulated right now, as it makes direct changes to ivars of
other objects.
Does anyone see any reason not to change nextKeyView to a single
object? Would someone familiar with that code like to make the
change? (In particular, I'm unsure whether there may be other
classes besides NSView that might be impacted…)
I think you are misunderstanding the code here. Each view already
has at most one next and previous key view, which is saved in the
first element of the respective arrays. The remaining elements of
the arrays are used to keep track of those views that refer to this
view as their next and previous key view, respectively. For
instance, given the statements
[P1 setNextKeyView: V];
[P2 setNextKeyView: V];
[P3 setNextKeyView: V];
[V setNextKeyView: N1];
[V setNextKeyView: N2];
[V setNextKeyView: N3];
you will end up with the following situation (sorry for the poor
ASCII art, you'll need a fixed pitch font to view this correctly):
+-- nextKV ->---\
P1 -- nextKV ->-+ | +-<- prevKV -- N3
\|/
P2 -- nextKV ->-- V --<- prevKV -- N2
/|\
P3 -- nextKV ->-+ | +-<- prevKV -- N1
\--<- prevKV --+
Note that the previous key view of V is P3 and the next key view is
N3. The pointers to P1, P2, N1, and N2 must be kept in the previous
key and next key view arrays so that the nextKV pointers of P1, P2,
and P3 and the prevKV pointers of N1, N2, and N3 can be reset when V
is deallocated, which is necessary to prevent crashes of the sort
you were experiencing.
Thanks Wolfgang
interesting ... good point and great explanation :-)
But what you describe (multiple views with the next key view set to
the same view) seems like a programming (and user interface) error,
so is it worth complicating the implementation to support it -
wouldn't we rather have the implementation try to fix it and keep the
next key
view "loop" consistent ? :-)
The next key view loop that you describe is problematic for the user
when navigating. If you are on P2 and hit 'TAB' to go from P2 to V,
then when you hit 'shift-TAB' to go back to P2,
the system would unexpectedly send you back to another view (P3 if I
read your diagram correctly). That's not good. Really, 'shift-TAB'
must undo exactly the navigation action that 'TAB' did,
so if TAB goes from P2 to V, then 'shift-TAB' must go from V to P2. I
personally use TABs often and get upset when I'm hit by this problem
which is typical of low-quality Windowish user interfaces - typically
you TAB quickly to get to the view you want, but then often you hit
one TAB more than needed and get past it, so you then try to go back
to it by hitting 'shift-TAB' and are irritatingly sent
to some place totally unrelated in the window. As 'shift-TAB'
produces unpredictable results, the only way to get back to where you
want to be in a predictable time is then to hit TAB again
and again and again hoping that the window loop is closed and after
TABbing long enough you'll get back to the start of the window and can
then TAB your way back to the view you want (and being
careful not to miss it again else you'll have to frantically TAB your
way out again). Irritating. :-(
I seem to remember that the API was built in such a way as to prevent
this from ever happening. IIRC calling setNextKeyView: seems so
innocent and "localized", but it actually does quite a bit of work
in other views to keep the next key view loop consistent. And IIRC
'setPreviousKeyView:' was removed by Apple at some point - that makes
it even more obvious that 'setNextKeyView:' is expected
to modify things in other views to keep the key view loop
consistent. :-)
So the situation you describe could (should ?) be made impossible -
when you call [P2 setNextKeyView: V];, that would completely undo what
[P1 setNextKeyView: V]; did. It would detect
that V already has a previous key view, and would terminate that by
setting both (V->PreviousKeyView)->NextKeyView and V->PreviousKeyView
to nil before starting to configure the
new next key view. Then any 'TAB' action would always be undoable by
using 'shift-TAB', and the memory management is simpler :-)
And I agree with Doug that this thing about views editing internals of
other views is not that inspiring/beautiful. An alternative
(better ?) API would have the 'next key view'
as an NSArray instance variable of the NSWindow, and NSWindow would
have the methods to manipulate it. The implementation would then be
quite simple and clear, but
have obviously a different feeling as information on the next key view
loop would be taken out of the specific views and become part of the
window, with all the consequences
eg for NIBs etc.
Thanks
_______________________________________________
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev