Drawing on top of a WebView

Discussion in 'Mac Programming' started by beon, Sep 25, 2008.

  1. macrumors newbie

    Joined:
    Sep 25, 2008
    Location:
    LA CA
    #1
    I've been beating my head against this for almost a week, and've done a lot of searching - so if I've missed the obvious reference and this question is redundant, it's not that I didn't look. That said...

    I want to be able to draw rectangles around specific content in a WebView. Say I have:
    Code:
    DOMNode * theNode = (some node in the DOMDocument of the current MainFrame);
    NSRect nodeRect = [theNode boundingBox];
    NSFrameRect(nodeRect);
    That draws a correctly sized rectangle, but the placement is way off - for reasons I'm pretty sure I understand. Apparently, boundingBox gives me a point of origin relative to the WebFrameView object that was used to display the node. But when I call NSFrameRect, it draws from the application's origin. Or something.

    So here's my question: how can I make the NSRect I get from boundingBox show up on top of the right place in the web view, and stay there?

    I've looked through the Apple documentation on webviews, webframes, webframeviews, drawing in cocoa, coordinate systems, bezierpaths... all to no avail. I'd greatly appriciate any help yall can offer.

    -Beon.
     
  2. macrumors 603

    whooleytoo

    Joined:
    Aug 2, 2002
    Location:
    Cork, Ireland.
    #2
    Haven't used WebViews all that much, so I'm not sure.

    Could it be as simple as you need to offset all rectangles by the origin of the WebFrameView?
     
  3. macrumors 601

    HiRez

    Joined:
    Jan 6, 2004
    Location:
    Western US
    #3
    Have a look at the NSWindow methods

    Code:
    - (NSPoint)convertBaseToScreen:(NSPoint)aPoint
    - (NSPoint)convertScreenToBase:(NSPoint)aPoint
    Also, you could maybe intercept the web document rendering and draw directly into the web document using CSS or Javascript, that way your rectangle could stay locked to the content it's highlighting even if the user scrolls it.
     
  4. thread starter macrumors newbie

    Joined:
    Sep 25, 2008
    Location:
    LA CA
    #4
    I do, but then I need to clip them at the edges of the WebView, which is doable but a bit of a pain. So let's try it. I'm gonna use
    Code:
    - (NSRect)convertRect:(NSRect)aRect fromView:(NSView *)aView
    rather than
    Code:
    - (NSPoint)convertScreenToBase:(NSPoint)aPoint
    That makes sense, yeah? That way I won't have to move the origin around every time I want to draw inside a different WebFrameView (of which there are often several in a single WebView).

    Will post progress.

    I haven't ruled out using javascript functions - it'd be especially easy since I'm already dealing with DOMNode objects, but darnit I'm going somewhere with this - somewhere cocoa - and more JS feels like a giant step butt-wards. :apple:
     
  5. Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #5
    I'm not sure how reliable boundingBox is. Either way you may have to convert that like HiRez said, plus the Y coordinates may be flipped.

    I don't think a WebView is doing anything too crazy with its subviews, unlike a QTMovieView. So you should be able to add a subview to the WebView, making sure it's on top (see addSubview:positioned:relativeTo: and NSWindowAbove).

    But I'd say JavaScript might be your best bet. You could create a Canvas element and draw your circle inside that, and then position that Canvas into the webpage.

    Edit: seems like WebKit's DOM handling lets you add child nodes, so that may work better instead of using JS since it's all in Cocoa/Obj-C.
     
  6. thread starter macrumors newbie

    Joined:
    Sep 25, 2008
    Location:
    LA CA
    #6
    Ya ya. Hm. How do you think they did Safari's "Find As You Type" results?
     
  7. Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #7
    I'm not sure. That functionality is built-in to WebKit (WebView has a public method for performing the search), so you could see if it's part of the open-source WebKit and then take a look at the source code.
     
  8. thread starter macrumors newbie

    Joined:
    Sep 25, 2008
    Location:
    LA CA
    #8
    Found this in WebDocumentPrivate.h:
    Code:
    @protocol WebDocumentSelection <WebDocumentText>
    - (NSArray *)pasteboardTypesForSelection;
    - (void)writeSelectionWithPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard;
    
    // Array of rects that tightly enclose the selected text, in coordinates of selectinView.
    - (NSArray *)selectionTextRects;
    
    // Rect tightly enclosing the entire selected area, in coordinates of selectionView.
    - (NSRect)selectionRect;
    
    // NSImage of the portion of the selection that's in view. This does not draw backgrounds. 
    // The text is all black according to the parameter.
    - (NSImage *)selectionImageForcingBlackText:(BOOL)forceBlackText;
    
    // NSImage of the portion of the selection that's in view. This does not draw backgrounds. 
    // The text is all white according to the parameter.
    // NOTE: This method is deprecated. It has been supplanted by selectionImageForcingBlackText:, 
    // and implementations typically just call that method, so its name no longer matches its
    // behavior. It will be removed when doing so won't cause trouble for people using the latest
    // WebKit with beta releases of Safari 3.0.
    - (NSImage *)selectionImageForcingWhiteText:(BOOL)forceWhiteText;
    
    // Rect tightly enclosing the entire selected area, in coordinates of selectionView.
    // NOTE: This method is equivalent to selectionRect and shouldn't be used; use selectionRect instead.
    - (NSRect)selectionImageRect;
    
    // View that draws the selection and can be made first responder. Often this is self but it could be
    // a nested view, as for example in the case of WebPDFView.
    - (NSView *)selectionView;
    @end
    Now that I take a better look at it, this solution doesn't look so good. There's a view over the whole mainFrame, with images (and maybe masks?) onzeetop of it, and it goes away when you try to interact with the web page.

    Seems like it might be easier to subclass WebFrameView. Maybe not. I have to do the stuff I'm getting paid to do for a bit now.
     

Share This Page