views:

384

answers:

3

I have a CGContext, which I can turn into an NSGraphicsContext. I have an NSWindow with a clipRect for the context.

I want to put a scrollview into the context and then some other view into the scrollview so I can put an image into it... However, I can't figure out how to attach the scrollview into the context.

Eventually the view will probably be coming from a nib, but I don't see how that would matter.

I've seen this thread, (http://lists.apple.com/archives/quartz-dev/2006/Nov/msg00010.html) But they seem to leave off the step of how to attach the view into the context, unless there's something obvious I'm missing.

EDIT:

The reason I'm in this situation is that I'm writing a Mozilla Plugin. The browser gives me a CGContext (Quartz) and a WindowRef (QuickDraw). I can turn the CGContext into an NSGraphicsContext, and I can turn the windowRef into an NSWindow. From another data structure I also have the clipping rectangle...

I'm trying to draw an image into that context, with scrollbars as needed, and buttons and other UI elements... so I need (want) an NSView...

A: 

You can't put a view into a graphics context. A view goes either into another view, or as the content view of a window.

You can draw a view into a context by setting that context as the current context and telling the view to draw. You might do this as a means of rendering the view to an image, but otherwise, I can't think of a reason to do it. (Edit: OK, being a Netscape plug-in is probably a good reason.)

Normally, a view gets its own graphics context in NSView's implementation of the lockFocus method, which is called for you by display, which is called for you by displayIfNeeded (only if the view needs display, obviously), which is called for you as part of the event loop.

You don't need to create a context for a view except in very rare circumstances, such as the export-to-an-image case I mentioned. Normally, you let the view take care of that itself.

Peter Hosey
The problem is that I don't HAVE a view. I have a context. I think I'll add some back-story to the original question...
Brian Postow
If you don't have a view, drawing it is going to be hard. Once you have a view, you can draw it into your context using the procedure I outlined. Of course, you'll still need to translate events and send them to the view.
Peter Hosey
Well, once I have a view I can just draw to the view using normal via normal drawing routines... but yeah, the problem is getting a view.
Brian Postow
Brian Postow: How to create a view would be a completely different question.
Peter Hosey
A: 

A partial solution?

What I have done currently is create a nib with a button in an IKImageView inside an NSScrollView. I load this in my plugin.

Then, since I have the NSWindow, I can get the contentView of the window. Then, I add the scrollview as subview of contentView.

It appears, but there seems to be some coordinate confusion about where the origin is. (top vs bottom) and since I'm mucking with the contentview of the WHOLE WINDOW, I'm doing some stuff very globally that perhaps I should be doing more locally. Like, the view never disappears, even when you close the tab, or go to another tab. (it does close when you close the window of course)

So, does this sound like a reasonable way of doing this? it feels a bit ... kludgy...

Brian Postow
A: 

For future generations (and me when I forget how I did this and Google leads me back to my own question) Here's how I'm doing this:

I have a NIB with all my views, I load this on start-up.

on SetWindow, I set the clip rect and actually do the attaching:

NP_CGContext* npContext = (NP_CGContext*) window->window;   
NSWindow* browserWindow = [[[NSWindow alloc] initWithWindowRef:npContext->window] autorelease];

NSView* cView = [browserWindow contentView];
NSView* hitView = [cView hitTest:NSMakePoint(window->x + 1, clip.origin.y + 1)];
if (hitView == nil || ![[hitView className] isEqualToString:@"ChildView"]) 
{
    return;
}

superView = [hitView retain];

[superView addSubview: topView];

[superView setNextResponder: topView];
[topView  setNextResponder: nil];
[browserWindow makeFirstResponder: topView];

To make sure I only addSubView once, I have a flag...

And then in handleEvent, I actually draw, Because I'm using an IKImageView, I can use the undocumented method: [imageView setImage: image]; which takes an NSImage.

So far this seems to be working for me. Hopefully this helps someone else.

Brian Postow