views:

43

answers:

3

I have an NSTextView in an NSScrollView, and I am programmatically inserting an NSView subclass as a subview of the NSTextView. This NSView acts as an overlay, superimposing graphical information about the text beneath it.

I thought it was working quite well until I noticed that the text view does not respond to right clicks. Other operations (editing, selection) seem to work just fine.

Also, if the first responder is changed to a sibling of the scroll view (an outline view, for example) the text view does not regain first responder status from clicking on it. The selection will change in response to clicking, but the selection highlight is gray instead of blue (indicating that the text view is not the first responder).

If I offset the frame of the overlay subview, the text view behaves 100% normally in the area not overlapped by the overlay, but the overlapped area behaves incorrectly, as outlined above.

Steps To Replicate This Behavior on Mac OS X 10.6.4:

  1. Create a plain old non-document-based Cocoa app.
  2. Add an `NSTextView' IBOutlet to the app delegate .h.
  3. Add an NSTextView to the window in MainMenu.xib. Connect the textView outlet.
  4. Type in a bit of code:

In applicationDidFinishLaunching:

NSView *overlay = [[NSView alloc] initWithFrame:textView.bounds];
[textView addSubview:overlay];
[overlay release];

Run the app, observe that right click in the text area does not work as it should, yet you can still otherwise interact with the text view.

Next, add an NSOutlineView to the window in the xib. Observe that once focus leaves the text area (if you click on the outline view) with the overlay in place, you cannot set the focus back to the text view (it will not become first responder again).


Is there some way I can enable the NSTextView to receive all of its events, even though my NSView overlay does not accept first responder or mouse events? I suspect this might be related to the field editor – perhaps it is ignoring events it thinks are destined to the overlay view?

A: 

Overlapping views is not supported well in Cocoa.

A better approach would be to create a borderless child window and draw the graphics in it. See the Movie Overlay sample app.

Nathan Kinsinger
Is this still an issue in 10.6? I've read that 10.4 and previous doesn't handle overlapping views, but that was with respect to sibling views that overlap each other. - - - Regarding the borderless child window: I'd consider this a last resort approach, given that the text view will be scrolling within the scroll view; it seems cumbersome to reflect the scrolling within the child window if it's possible to do it more simply.
Adam Preble
Nathan Kinsinger: Overlapping *sibling* views is not supported well. The questioner's STR say he is adding the overlay as a subview of the text view; subviews overlap their superviews by necessity.
Peter Hosey
A: 

I don't have a lot of experience with it, but another possibility would be to use a Core Animation layer as an overlay.

JWWalker
Appreciate the suggestion, however I'm specifically interested in responding to mouse events and would prefer not to reinvent the wheel with respect to mapping them to sublayers, etc.
Adam Preble
+1  A: 

You probably need to make your overlay an instance of a custom view class that forwards all events and accessibility messages to the text view. You may also need to convert any view-relative coordinates to the text view's coordinate system.

Peter Hosey