WebKit/mac/WebInspector/WebNodeHighlight.mm
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 2007, 2008 Apple Inc.  All rights reserved.
       
     3  *
       
     4  * Redistribution and use in source and binary forms, with or without
       
     5  * modification, are permitted provided that the following conditions
       
     6  * are met:
       
     7  *
       
     8  * 1.  Redistributions of source code must retain the above copyright
       
     9  *     notice, this list of conditions and the following disclaimer. 
       
    10  * 2.  Redistributions in binary form must reproduce the above copyright
       
    11  *     notice, this list of conditions and the following disclaimer in the
       
    12  *     documentation and/or other materials provided with the distribution. 
       
    13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
       
    14  *     its contributors may be used to endorse or promote products derived
       
    15  *     from this software without specific prior written permission. 
       
    16  *
       
    17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
       
    18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
       
    19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
       
    20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
       
    21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
       
    22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
       
    23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
       
    24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
       
    26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    27  */
       
    28 
       
    29 #import "WebNodeHighlight.h"
       
    30 #import "WebNodeHighlightView.h"
       
    31 #import "WebNSViewExtras.h"
       
    32 
       
    33 #import <WebCore/InspectorController.h>
       
    34 #import <wtf/Assertions.h>
       
    35 
       
    36 using namespace WebCore;
       
    37 
       
    38 @interface WebNodeHighlight (FileInternal)
       
    39 - (NSRect)_computeHighlightWindowFrame;
       
    40 - (void)_repositionHighlightWindow;
       
    41 @end
       
    42 
       
    43 @implementation WebNodeHighlight
       
    44 
       
    45 - (id)initWithTargetView:(NSView *)targetView inspectorController:(InspectorController*)inspectorController
       
    46 {
       
    47     self = [super init];
       
    48     if (!self)
       
    49         return nil;
       
    50 
       
    51     _targetView = [targetView retain];
       
    52     _inspectorController = inspectorController;
       
    53 
       
    54     int styleMask = NSBorderlessWindowMask;
       
    55     NSRect contentRect = [NSWindow contentRectForFrameRect:[self _computeHighlightWindowFrame] styleMask:styleMask];
       
    56     _highlightWindow = [[NSWindow alloc] initWithContentRect:contentRect styleMask:styleMask backing:NSBackingStoreBuffered defer:NO];
       
    57     [_highlightWindow setBackgroundColor:[NSColor clearColor]];
       
    58     [_highlightWindow setOpaque:NO];
       
    59     [_highlightWindow setIgnoresMouseEvents:YES];
       
    60     [_highlightWindow setReleasedWhenClosed:NO];
       
    61 
       
    62     _highlightView = [[WebNodeHighlightView alloc] initWithWebNodeHighlight:self];
       
    63     [_highlightWindow setContentView:_highlightView];
       
    64     [_highlightView release];
       
    65 
       
    66     return self;
       
    67 }
       
    68 
       
    69 - (void)dealloc
       
    70 {
       
    71     ASSERT(!_highlightWindow);
       
    72     ASSERT(!_targetView);
       
    73     ASSERT(!_highlightView);
       
    74 
       
    75     [super dealloc];
       
    76 }
       
    77 
       
    78 - (void)attach
       
    79 {
       
    80     ASSERT(_targetView);
       
    81     ASSERT([_targetView window]);
       
    82     ASSERT(_highlightWindow);
       
    83 
       
    84     if (!_highlightWindow || !_targetView || ![_targetView window])
       
    85         return;
       
    86 
       
    87     [[_targetView window] addChildWindow:_highlightWindow ordered:NSWindowAbove];
       
    88 
       
    89     // Observe both frame-changed and bounds-changed notifications because either one could leave
       
    90     // the highlight incorrectly positioned with respect to the target view. We need to do this for
       
    91     // the entire superview hierarchy to handle scrolling, bars coming and going, etc. 
       
    92     // (without making concrete assumptions about the view hierarchy).
       
    93     NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
       
    94     for (NSView *v = _targetView; v; v = [v superview]) {
       
    95         [notificationCenter addObserver:self selector:@selector(_repositionHighlightWindow) name:NSViewFrameDidChangeNotification object:v];
       
    96         [notificationCenter addObserver:self selector:@selector(_repositionHighlightWindow) name:NSViewBoundsDidChangeNotification object:v];
       
    97     }
       
    98 
       
    99     if (_delegate && [_delegate respondsToSelector:@selector(didAttachWebNodeHighlight:)])
       
   100         [_delegate didAttachWebNodeHighlight:self];
       
   101 }
       
   102 
       
   103 - (id)delegate
       
   104 {
       
   105     return _delegate;
       
   106 }
       
   107 
       
   108 - (void)detach
       
   109 {
       
   110     if (!_highlightWindow) {
       
   111         ASSERT(!_targetView);
       
   112         return;
       
   113     }
       
   114 
       
   115     if (_delegate && [_delegate respondsToSelector:@selector(willDetachWebNodeHighlight:)])
       
   116         [_delegate willDetachWebNodeHighlight:self];
       
   117 
       
   118     NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
       
   119     [notificationCenter removeObserver:self name:NSViewFrameDidChangeNotification object:nil];
       
   120     [notificationCenter removeObserver:self name:NSViewBoundsDidChangeNotification object:nil];
       
   121 
       
   122     [[_highlightWindow parentWindow] removeChildWindow:_highlightWindow];
       
   123 
       
   124     [_highlightWindow release];
       
   125     _highlightWindow = nil;
       
   126 
       
   127     [_targetView release];
       
   128     _targetView = nil;
       
   129 
       
   130     // We didn't retain _highlightView, but we do need to tell it to forget about us, so it doesn't
       
   131     // try to send our delegate messages after we've been dealloc'ed, e.g.
       
   132     [_highlightView detachFromWebNodeHighlight];
       
   133     _highlightView = nil;
       
   134 }
       
   135 
       
   136 - (WebNodeHighlightView *)highlightView
       
   137 {
       
   138     return _highlightView;
       
   139 }
       
   140 
       
   141 - (void)setDelegate:(id)delegate
       
   142 {
       
   143     // The delegate is not retained, as usual in Cocoa.
       
   144     _delegate = delegate;
       
   145 }
       
   146 
       
   147 - (void)setNeedsUpdateInTargetViewRect:(NSRect)rect
       
   148 {
       
   149     ASSERT(_targetView);
       
   150 
       
   151     [[_targetView window] disableScreenUpdatesUntilFlush];
       
   152 
       
   153     // Mark the whole highlight view as needing display since we don't know what areas
       
   154     // need updated, since the highlight can be larger than the element to show margins.
       
   155     [_highlightView setNeedsDisplay:YES];
       
   156 
       
   157     // Redraw highlight view immediately so it updates in sync with the target view.
       
   158     // This is especially visible when resizing the window, scrolling or with DHTML.
       
   159     [_highlightView displayIfNeeded];
       
   160 }
       
   161 
       
   162 - (NSView *)targetView
       
   163 {
       
   164     return _targetView;
       
   165 }
       
   166 
       
   167 - (InspectorController*)inspectorController
       
   168 {
       
   169     return _inspectorController;
       
   170 }
       
   171 
       
   172 @end
       
   173 
       
   174 @implementation WebNodeHighlight (FileInternal)
       
   175 
       
   176 - (NSRect)_computeHighlightWindowFrame
       
   177 {
       
   178     ASSERT(_targetView);
       
   179     ASSERT([_targetView window]);
       
   180 
       
   181     NSRect highlightWindowFrame = [_targetView convertRect:[_targetView visibleRect] toView:nil];
       
   182     highlightWindowFrame.origin = [[_targetView window] convertBaseToScreen:highlightWindowFrame.origin];
       
   183 
       
   184     return highlightWindowFrame;
       
   185 }
       
   186 
       
   187 - (void)_repositionHighlightWindow
       
   188 {
       
   189     // This assertion fires in cases where a new tab is created while the highlight
       
   190     // is showing (<http://bugs.webkit.org/show_bug.cgi?id=14254>)
       
   191     ASSERT([_targetView window]);
       
   192     
       
   193     // Until that bug is fixed, bail out to avoid worse problems where the highlight
       
   194     // moves to a nonsense location.
       
   195     if (![_targetView window])
       
   196         return;
       
   197 
       
   198     // Disable screen updates so the highlight moves in sync with the view.
       
   199     [[_targetView window] disableScreenUpdatesUntilFlush];
       
   200 
       
   201     [_highlightWindow setFrame:[self _computeHighlightWindowFrame] display:YES];
       
   202 }
       
   203 
       
   204 @end