WebCore:
authorthatcher <thatcher@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 16 Jan 2006 02:42:36 +0000 (02:42 +0000)
committerthatcher <thatcher@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 16 Jan 2006 02:42:36 +0000 (02:42 +0000)
        Reviewed by Darin.

        Support for the new DOM Inspector.

        * khtml/ecma/kjs_dom.cpp: exposes scrollIntoViewIfNeeded to JS
        * khtml/ecma/kjs_dom.h:
        * khtml/rendering/RenderText.cpp:
        (RenderText::lineBoxRects): returns text run rects
        * khtml/rendering/RenderText.h:
        * khtml/rendering/render_container.cpp:
        (RenderContainer::lineBoxRects): returns all child line box rects
        * khtml/rendering/render_container.h:
        * khtml/rendering/render_object.cpp:
        (RenderObject::lineBoxRects): returns an empty list
        * khtml/rendering/render_object.h:
        * khtml/xml/dom_elementimpl.cpp:
        (ElementImpl::scrollIntoViewIfNeeded): scrolls only if needed, bool decides to center to align to nearest edge
        * khtml/xml/dom_elementimpl.h: Ditto
        * kwq/DOM.mm:
        (-[DOMNode boundingBox]): returns the bounding box for a node
        (-[DOMNode lineBoxRects]): returns text runs for a node
        * kwq/DOMCore.h: added missing @protocol DOMEventListener and @class DOMEvent
        * kwq/DOMExtensions.h: removes methods that haven't been API reviewed
        * kwq/DOMPrivate.h: new pending public API added for the Inspector

WebKit:

        Reviewed by Darin.

        New DOM Inspector that lives in WebKit and is accessible from any WebView.
        Accessible from a contextual menu when the WebKitEnableInspectElementContextMenuItem default is
        true or you have a development build. Browsing the tree, serialized HTML and CSS rules work.

        To always enable enter the following in the Terminal (change the bundle id to affect other WebKit apps):
        defaults write com.apple.Safari WebKitEnableInspectElementContextMenuItem -bool true

        http://bugzilla.opendarwin.org/show_bug.cgi?id=6571

        * English.lproj/Localizable.strings:
        * English.lproj/StringsNotToBeLocalized.txt: reorder of the entries
        * Misc.subproj/WebKitNSStringExtras.h:
        * Misc.subproj/WebKitNSStringExtras.m:
        (-[NSString _webkit_stringByCollapsingWhitespaceCharacters]): collapses consecutive whitespace into a single space
        * WebCoreSupport.subproj/WebFrameBridge.m:
        (-[WebFrameBridge pluginViewWithPackage:attributeNames:attributeValues:baseURL:]): cleanup
        (-[WebFrameBridge viewForPluginWithURL:attributeNames:attributeValues:MIMEType:]): call the new UI delegate method
        * WebInspector.subproj: Added.
        * WebInspector.subproj/WebInspector.h: Added.
        * WebInspector.subproj/WebInspector.m: Added.
        (+[WebInspector sharedWebInspector]):
        (-[WebInspector init]):
        (-[WebInspector initWithWebFrame:]):
        (-[WebInspector dealloc]):
        (-[WebInspector window]):
        (-[WebInspector windowDidLoad]):
        (-[WebInspector windowWillClose:]):
        (-[WebInspector showWindow:]):
        (-[WebInspector setWebFrame:]):
        (-[WebInspector webFrame]):
        (-[WebInspector setRootDOMNode:]):
        (-[WebInspector rootDOMNode]):
        (-[WebInspector setFocusedDOMNode:]):
        (-[WebInspector focusedDOMNode]):
        (-[WebInspector setSearchQuery:]):
        (-[WebInspector searchQuery]):
        (-[WebInspector searchResults]):
        (-[WebInspector showOptionsMenu]):
        (-[WebInspector selectNewRoot:]):
        (-[WebInspector resizeTopArea:]):
        (-[WebInspector treeViewScrollTo:]):
        (-[WebInspector treeViewOffsetTop]):
        (-[WebInspector treeViewScrollHeight]):
        (-[WebInspector traverseTreeBackward]):
        (-[WebInspector traverseTreeForward]):
        (-[WebInspector _toggleIgnoreWhitespace:]):
        (-[WebInspector _highlightNode:]):
        (-[WebInspector _nodeHighlightExpired:]):
        (-[WebInspector _focusRootNode:]):
        (-[WebInspector _revealAndSelectNodeInTree:]):
        (-[WebInspector _showSearchResults:]):
        (-[WebInspector _refreshSearch]):
        (-[WebInspector _update]):
        (-[WebInspector _updateRoot]):
        (-[WebInspector _updateTreeScrollbar]):
        (+[WebInspector isSelectorExcludedFromWebScript:]):
        (+[WebInspector webScriptNameForSelector:]):
        (+[WebInspector isKeyExcludedFromWebScript:]):
        (-[WebInspector handleEvent:]):
        (-[WebInspector webView:didFinishLoadForFrame:]):
        (-[WebInspector webView:plugInViewWithArguments:]):
        (-[WebInspector outlineView:numberOfChildrenOfItem:]):
        (-[WebInspector outlineView:isItemExpandable:]):
        (-[WebInspector outlineView:child:ofItem:]):
        (-[WebInspector outlineView:objectValueForTableColumn:byItem:]):
        (-[WebInspector outlineView:willDisplayOutlineCell:forTableColumn:item:]):
        (-[WebInspector outlineViewItemDidCollapse:]):
        (-[WebInspector outlineViewSelectionDidChange:]):
        (-[WebInspectorPrivate dealloc]):
        (-[DOMHTMLElement _addClassName:]): Helper method for the Inspector to append style classes
        (-[DOMHTMLElement _removeClassName:]): Helper method for the Inspector to remove style classes
        (-[DOMNode _contentPreview]):
        (-[DOMNode _isAncestorOfNode:]):
        (-[DOMNode _isDescendantOfNode:]):
        (-[DOMNode _isWhitespace]):
        (-[DOMNode _lengthOfChildNodesIgnoringWhitespace]):
        (-[DOMNode _childNodeAtIndexIgnoringWhitespace:]):
        (-[DOMNode _nextSiblingSkippingWhitespace]):
        (-[DOMNode _previousSiblingSkippingWhitespace]):
        (-[DOMNode _firstChildSkippingWhitespace]):
        (-[DOMNode _lastChildSkippingWhitespace]):
        (-[DOMNode _firstAncestorCommonWithNode:]):
        (-[DOMNode _traverseNextNodeStayingWithin:]):
        (-[DOMNode _traverseNextNodeSkippingWhitespaceStayingWithin:]):
        (-[DOMNode _traversePreviousNode]):
        (-[DOMNode _traversePreviousNodeSkippingWhitespace]):
        (-[DOMNode _nodeTypeName]):
        (-[DOMNode _shortDisplayName]):
        (-[DOMNode _displayName]):
        * WebInspector.subproj/WebInspectorInternal.h: Added.
        * WebInspector.subproj/WebInspectorOutlineView.h: Added.
        * WebInspector.subproj/WebInspectorOutlineView.m: Added.
        (-[WebInspectorOutlineView isOpaque]):
        (-[WebInspectorOutlineView _highlightColorForCell:]):
        (-[WebInspectorOutlineView _highlightRow:clipRect:]):
        (-[WebInspectorOutlineView drawBackgroundInClipRect:]):
        * WebInspector.subproj/WebInspectorPanel.h: Added.
        * WebInspector.subproj/WebInspectorPanel.m: Added.
        (-[WebInspectorPanel canBecomeKeyWindow]):
        (-[WebInspectorPanel canBecomeMainWindow]):
        (-[WebInspectorPanel moveWindow:]):
        (-[WebInspectorPanel resizeWindow:]):
        (-[WebInspectorPanel sendEvent:]):
        * WebInspector.subproj/WebNodeHighlight.h: Added.
        * WebInspector.subproj/WebNodeHighlight.m: Added.
        (-[WebNodeHighlight initWithBounds:andRects:forView:]):
        (-[WebNodeHighlight dealloc]):
        (-[WebNodeHighlight fractionComplete]):
        (-[WebNodeHighlight expire]):
        (-[WebNodeHighlight redraw:]):
        * WebInspector.subproj/WebNodeHighlightView.h: Added.
        * WebInspector.subproj/WebNodeHighlightView.m: Added.
        (-[WebNodeHighlightView roundedRect:withRadius:]):
        (-[WebNodeHighlightView initWithHighlight:andRects:forView:]):
        (-[WebNodeHighlightView dealloc]):
        (-[WebNodeHighlightView isOpaque]):
        (-[WebNodeHighlightView drawRect:]):
        * WebInspector.subproj/webInspector: Added.
        * WebInspector.subproj/webInspector/Images: Added.
        * WebInspector.subproj/webInspector/Images/close.png: Added.
        * WebInspector.subproj/webInspector/Images/closePressed.png: Added.
        * WebInspector.subproj/webInspector/Images/downTriangle.png: Added.
        * WebInspector.subproj/webInspector/Images/menu.png: Added.
        * WebInspector.subproj/webInspector/Images/menuPressed.png: Added.
        * WebInspector.subproj/webInspector/Images/popupFill.png: Added.
        * WebInspector.subproj/webInspector/Images/popupFillPressed.png: Added.
        * WebInspector.subproj/webInspector/Images/popupLeft.png: Added.
        * WebInspector.subproj/webInspector/Images/popupLeftPressed.png: Added.
        * WebInspector.subproj/webInspector/Images/popupRight.png: Added.
        * WebInspector.subproj/webInspector/Images/popupRightPressed.png: Added.
        * WebInspector.subproj/webInspector/Images/rightTriangle.png: Added.
        * WebInspector.subproj/webInspector/Images/scrollThumbBottom.png: Added.
        * WebInspector.subproj/webInspector/Images/scrollThumbMiddle.png: Added.
        * WebInspector.subproj/webInspector/Images/scrollThumbTop.png: Added.
        * WebInspector.subproj/webInspector/Images/scrollTrackBottom.png: Added.
        * WebInspector.subproj/webInspector/Images/scrollTrackMiddle.png: Added.
        * WebInspector.subproj/webInspector/Images/scrollTrackTop.png: Added.
        * WebInspector.subproj/webInspector/Images/squareButtonRight.png: Added.
        * WebInspector.subproj/webInspector/Images/squareButtonRightPressed.png: Added.
        * WebInspector.subproj/webInspector/Images/upTriangle.png: Added.
        * WebInspector.subproj/webInspector/inspector.css: Added.
        * WebInspector.subproj/webInspector/inspector.html: Added.
        * WebInspector.subproj/webInspector/inspector.js: Added.
        * WebKit.xcodeproj/project.pbxproj: Adds Web Inspector files
        * WebView.subproj/WebUIDelegatePrivate.h: new UI delegate method to supply a replacement view for plugins
        * WebView.subproj/WebView.m:
        (-[WebView _menuForElement:defaultItems:]): Add a new context menu item for inspecting
        (-[WebView _inspectElement:]): Context menu item target for inspecting

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@12122 268f45cc-cd09-0410-ab3c-d52691b4dbfc

59 files changed:
WebCore/ChangeLog
WebCore/khtml/ecma/kjs_dom.cpp
WebCore/khtml/ecma/kjs_dom.h
WebCore/khtml/rendering/RenderText.cpp
WebCore/khtml/rendering/RenderText.h
WebCore/khtml/rendering/render_container.cpp
WebCore/khtml/rendering/render_container.h
WebCore/khtml/rendering/render_object.cpp
WebCore/khtml/rendering/render_object.h
WebCore/khtml/xml/dom_elementimpl.cpp
WebCore/khtml/xml/dom_elementimpl.h
WebCore/kwq/DOM.mm
WebCore/kwq/DOMCore.h
WebCore/kwq/DOMExtensions.h
WebCore/kwq/DOMPrivate.h
WebKit/ChangeLog
WebKit/English.lproj/Localizable.strings
WebKit/English.lproj/StringsNotToBeLocalized.txt
WebKit/Misc.subproj/WebKitNSStringExtras.h
WebKit/Misc.subproj/WebKitNSStringExtras.m
WebKit/WebCoreSupport.subproj/WebFrameBridge.m
WebKit/WebInspector.subproj/WebInspector.h [new file with mode: 0644]
WebKit/WebInspector.subproj/WebInspector.m [new file with mode: 0644]
WebKit/WebInspector.subproj/WebInspectorInternal.h [new file with mode: 0644]
WebKit/WebInspector.subproj/WebInspectorOutlineView.h [new file with mode: 0644]
WebKit/WebInspector.subproj/WebInspectorOutlineView.m [new file with mode: 0644]
WebKit/WebInspector.subproj/WebInspectorPanel.h [new file with mode: 0644]
WebKit/WebInspector.subproj/WebInspectorPanel.m [new file with mode: 0644]
WebKit/WebInspector.subproj/WebNodeHighlight.h [new file with mode: 0644]
WebKit/WebInspector.subproj/WebNodeHighlight.m [new file with mode: 0644]
WebKit/WebInspector.subproj/WebNodeHighlightView.h [new file with mode: 0644]
WebKit/WebInspector.subproj/WebNodeHighlightView.m [new file with mode: 0644]
WebKit/WebInspector.subproj/webInspector/Images/close.png [new file with mode: 0644]
WebKit/WebInspector.subproj/webInspector/Images/closePressed.png [new file with mode: 0644]
WebKit/WebInspector.subproj/webInspector/Images/downTriangle.png [new file with mode: 0644]
WebKit/WebInspector.subproj/webInspector/Images/menu.png [new file with mode: 0644]
WebKit/WebInspector.subproj/webInspector/Images/menuPressed.png [new file with mode: 0644]
WebKit/WebInspector.subproj/webInspector/Images/popupFill.png [new file with mode: 0644]
WebKit/WebInspector.subproj/webInspector/Images/popupFillPressed.png [new file with mode: 0644]
WebKit/WebInspector.subproj/webInspector/Images/popupLeft.png [new file with mode: 0644]
WebKit/WebInspector.subproj/webInspector/Images/popupLeftPressed.png [new file with mode: 0644]
WebKit/WebInspector.subproj/webInspector/Images/popupRight.png [new file with mode: 0644]
WebKit/WebInspector.subproj/webInspector/Images/popupRightPressed.png [new file with mode: 0644]
WebKit/WebInspector.subproj/webInspector/Images/rightTriangle.png [new file with mode: 0644]
WebKit/WebInspector.subproj/webInspector/Images/scrollThumbBottom.png [new file with mode: 0644]
WebKit/WebInspector.subproj/webInspector/Images/scrollThumbMiddle.png [new file with mode: 0644]
WebKit/WebInspector.subproj/webInspector/Images/scrollThumbTop.png [new file with mode: 0644]
WebKit/WebInspector.subproj/webInspector/Images/scrollTrackBottom.png [new file with mode: 0644]
WebKit/WebInspector.subproj/webInspector/Images/scrollTrackMiddle.png [new file with mode: 0644]
WebKit/WebInspector.subproj/webInspector/Images/scrollTrackTop.png [new file with mode: 0644]
WebKit/WebInspector.subproj/webInspector/Images/squareButtonRight.png [new file with mode: 0644]
WebKit/WebInspector.subproj/webInspector/Images/squareButtonRightPressed.png [new file with mode: 0644]
WebKit/WebInspector.subproj/webInspector/Images/upTriangle.png [new file with mode: 0644]
WebKit/WebInspector.subproj/webInspector/inspector.css [new file with mode: 0644]
WebKit/WebInspector.subproj/webInspector/inspector.html [new file with mode: 0644]
WebKit/WebInspector.subproj/webInspector/inspector.js [new file with mode: 0644]
WebKit/WebKit.xcodeproj/project.pbxproj
WebKit/WebView.subproj/WebUIDelegatePrivate.h
WebKit/WebView.subproj/WebView.m

index 3f87fbb809fc09c0e7452fe8e6df00c43ce6aca1..257629d0ebddf73ebcc5a8bceccdb35b33dcd894 100644 (file)
@@ -1,3 +1,30 @@
+2006-01-15  Timothy Hatcher  <timothy@apple.com>
+
+        Reviewed by Darin.
+
+        Support for the new DOM Inspector.
+
+        * khtml/ecma/kjs_dom.cpp: exposes scrollIntoViewIfNeeded to JS
+        * khtml/ecma/kjs_dom.h:
+        * khtml/rendering/RenderText.cpp:
+        (RenderText::lineBoxRects): returns text run rects
+        * khtml/rendering/RenderText.h:
+        * khtml/rendering/render_container.cpp:
+        (RenderContainer::lineBoxRects): returns all child line box rects
+        * khtml/rendering/render_container.h:
+        * khtml/rendering/render_object.cpp:
+        (RenderObject::lineBoxRects): returns an empty list
+        * khtml/rendering/render_object.h:
+        * khtml/xml/dom_elementimpl.cpp:
+        (ElementImpl::scrollIntoViewIfNeeded): scrolls only if needed, bool decides to center to align to nearest edge
+        * khtml/xml/dom_elementimpl.h: Ditto
+        * kwq/DOM.mm:
+        (-[DOMNode boundingBox]): returns the bounding box for a node
+        (-[DOMNode lineBoxRects]): returns text runs for a node
+        * kwq/DOMCore.h: added missing @protocol DOMEventListener and @class DOMEvent
+        * kwq/DOMExtensions.h: removes methods that haven't been API reviewed
+        * kwq/DOMPrivate.h: new pending public API added for the Inspector
+
 2006-01-15  Darin Adler  <darin@apple.com>
 
         Reviewed by Eric.
index e7dcdbafb25b3c3e105f1cee1da73b6dea367bc5..463752edec9a11faf28d0a576f6a90f337476c20 100644 (file)
@@ -1110,6 +1110,7 @@ JSValue *DOMDocumentProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj
   getElementsByTagNameNS DOMElement::GetElementsByTagNameNS    DontDelete|Function 2
   hasAttributeNS       DOMElement::HasAttributeNS      DontDelete|Function 2
   scrollIntoView        DOMElement::ScrollIntoView      DontDelete|Function 1
+  scrollIntoViewIfNeeded       DOMElement::ScrollIntoViewIfNeeded      DontDelete|Function 1
   focus                 DOMElement::ElementFocus        DontDelete|Function 0
   blur                  DOMElement::ElementBlur         DontDelete|Function 0
 
@@ -1243,6 +1244,9 @@ JSValue *DOMElementProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj,
     case DOMElement::ScrollIntoView: 
         element.scrollIntoView(args[0]->isUndefinedOrNull() || args[0]->toBoolean(exec));
         return jsUndefined();
+    case DOMElement::ScrollIntoViewIfNeeded: 
+        element.scrollIntoViewIfNeeded(args[0]->isUndefinedOrNull() || args[0]->toBoolean(exec));
+        return jsUndefined();
     case DOMElement::ScrollByLines:
     case DOMElement::ScrollByPages:
       if (DocumentImpl* doc = element.getDocument()) {
index 8ae8476cef9a74dc7e2140d8847feeaef5579f56..d7b21f3ea2636e19c9cc1361481600fbc06277c0 100644 (file)
@@ -77,7 +77,8 @@ namespace KJS {
            OnMouseMove, OnMouseOut, OnMouseOver, OnMouseUp, OnMouseWheel, OnMove, OnReset,
            OnResize, OnScroll, OnSearch, OnSelect, OnSubmit, OnUnload,
            OffsetLeft, OffsetTop, OffsetWidth, OffsetHeight, OffsetParent,
-           ClientWidth, ClientHeight, ScrollLeft, ScrollTop, ScrollWidth, ScrollHeight, ScrollIntoView };
+           ClientWidth, ClientHeight, ScrollLeft, ScrollTop, ScrollWidth, ScrollHeight,
+           ScrollIntoView, ScrollIntoViewIfNeeded };
 
   protected:
     // Constructor for inherited classes; doesn't set up a prototype.
index 740b1642f03599cbf69b135c46b4afe07a4ed2b5..9338b62493c83717c6af8ee322c9d654f9ce4944 100644 (file)
@@ -211,6 +211,15 @@ void RenderText::absoluteRects(QValueList<IntRect>& rects, int _tx, int _ty)
                            box->height()));
 }
 
+QValueList<IntRect> RenderText::lineBoxRects()
+{
+    QValueList<IntRect> rects;
+    int x = 0, y = 0;
+    absolutePosition(x, y);
+    absoluteRects(rects, x, y);
+    return rects;
+}
+
 InlineTextBox* RenderText::findNextInlineTextBox(int offset, int &pos) const
 {
     // The text runs point to parts of the rendertext's str string
index 0ff241b42c7f671de3487ccf596d758aabe9e86c..3fcf4904b9919a2fd8a73f0deecf2d5ab157995b 100644 (file)
@@ -80,6 +80,7 @@ public:
                              HitTestAction hitTestAction) { assert(false); return false; }
 
     virtual void absoluteRects(QValueList<IntRect>& rects, int _tx, int _ty);
+    virtual QValueList<IntRect> RenderText::lineBoxRects();
 
     virtual VisiblePosition positionForCoordinates(int x, int y);
 
index b19ea5d350114b08d35643630fbc96e56e9c70f6..636c648cdae96be3ce9bdde00439a41ab78f76ce 100644 (file)
@@ -490,5 +490,30 @@ VisiblePosition RenderContainer::positionForCoordinates(int _x, int _y)
     
     return VisiblePosition(element(), 0, DOWNSTREAM);
 }
-    
+
+QValueList<IntRect> RenderContainer::lineBoxRects()
+{
+    if (!firstChild() && (isInline() || isAnonymousBlock())) {
+        QValueList<IntRect> rects;
+        int x = 0, y = 0;
+        absolutePosition(x, y);
+        absoluteRects(rects, x, y);
+        return rects;
+    }
+
+    if (!firstChild())
+        return QValueList<IntRect>();
+
+    QValueList<IntRect> rects;
+    for (RenderObject *child = firstChild(); child; child = child->nextSibling()) {
+        if (child->isText() || child->isInline() || child->isAnonymousBlock()) {
+            int x = 0, y = 0;
+            child->absolutePosition(x, y);
+            child->absoluteRects(rects, x, y);
+        }
+    }
+
+    return rects;
+}
+
 #undef DEBUG_LAYOUT
index 9a56720090079eb11583bb9824fae515e8d973a0..2ca3b35006ea4039c0ae53cf5767903e665214f7 100644 (file)
@@ -63,6 +63,8 @@ public:
     void updatePseudoChild(RenderStyle::PseudoId type, RenderObject* child);
 
     virtual VisiblePosition positionForCoordinates(int x, int y);
+    
+    virtual QValueList<IntRect> lineBoxRects();
 
 protected:
     void setFirstChild(RenderObject *first) { m_first = first; }
index 241019e0b67262028c5bf3e9c6a0178d058ed4c9..57bc2907aeb2964ee3d68e01e2ab75f62d61445a 100644 (file)
@@ -1271,6 +1271,11 @@ void RenderObject::paintBorder(QPainter *p, int _tx, int _ty, int w, int h, cons
         p->restore(); // Undo the clip.
 }
 
+QValueList<IntRect> RenderObject::lineBoxRects()
+{
+    return QValueList<IntRect>();
+}
+
 void RenderObject::absoluteRects(QValueList<IntRect>& rects, int _tx, int _ty)
 {
     // For blocks inside inlines, we go ahead and include margins so that we run right up to the
@@ -1293,7 +1298,10 @@ IntRect RenderObject::absoluteBoundingBoxRect()
     absolutePosition(x, y);
     QValueList<IntRect> rects;
     absoluteRects(rects, x, y);
-    
+
+    if (rects.isEmpty())
+        return IntRect(0, 0, 0, 0);
+
     QValueList<IntRect>::ConstIterator it = rects.begin();
     IntRect result = *it;
     while (++it != rects.end()) {
index 44fc576ac74d80c3f24abea833fdb81e5f067746..649290e75d580f8296d639211162fc2faaaf94f2 100644 (file)
@@ -671,6 +671,8 @@ public:
     virtual int borderLeft() const { return style()->borderLeftWidth(); }
     virtual int borderRight() const { return style()->borderRightWidth(); }
 
+    virtual QValueList<IntRect> lineBoxRects();
+
     virtual void absoluteRects(QValueList<IntRect>& rects, int _tx, int _ty);
     IntRect absoluteBoundingBoxRect();
     
index afc14fe27e393912408c3c85cad7e5c3938710b2..5da24a21babc049b428d9a44dd2e4b9b99489922 100644 (file)
@@ -361,6 +361,17 @@ void ElementImpl::scrollIntoView(bool alignToTop)
     }
 }
 
+void ElementImpl::scrollIntoViewIfNeeded(bool centerIfNeeded)
+{
+    IntRect bounds = this->getRect();    
+    if (m_render) {
+        if (centerIfNeeded)
+            m_render->enclosingLayer()->scrollRectToVisible(bounds, RenderLayer::gAlignCenterIfNeeded, RenderLayer::gAlignCenterIfNeeded);
+        else
+            m_render->enclosingLayer()->scrollRectToVisible(bounds, RenderLayer::gAlignToEdgeIfNeeded, RenderLayer::gAlignToEdgeIfNeeded);
+    }
+}
+
 const AtomicString& ElementImpl::getAttributeNS(const DOMString &namespaceURI,
                                                 const DOMString &localName) const
 {
index b4bc73d5bc6d2a1986717a686db41b698c9cbe9f..be0465c78231e388b4e174ad56bfde63f9fd14d1 100644 (file)
@@ -194,7 +194,8 @@ public:
     void setAttributeNS(const DOMString &namespaceURI, const DOMString &qualifiedName, const DOMString &value, int &exception);
 
     void scrollIntoView (bool alignToTop);
-    
+    void scrollIntoViewIfNeeded(bool centerIfNeeded);
+
     void removeAttribute(const DOMString &name, int &exception) { removeAttributeNS(DOMString(), name, exception); }
     void removeAttributeNS(const DOMString &namespaceURI, const DOMString &localName, int &exception);
 
index a77d388a7de966bbb3bd277cb5cb521586d2c11a..9fa85fcdbde830a3f6211694e69cc5dd459ee0a6 100644 (file)
@@ -404,6 +404,29 @@ static ListenerMap *listenerMap;
     return result;
 }
 
+- (NSRect)boundingBox
+{
+    khtml::RenderObject *renderer = [self _nodeImpl]->renderer();
+    if (renderer)
+        return renderer->absoluteBoundingBoxRect();
+    return NSZeroRect;
+}
+
+- (NSArray *)lineBoxRects
+{
+    khtml::RenderObject *renderer = [self _nodeImpl]->renderer();
+    if (renderer) {
+        NSMutableArray *results = [[NSMutableArray alloc] init];
+        QValueList<IntRect> rects = renderer->lineBoxRects();
+        if (!rects.isEmpty()) {
+            for (QValueList<IntRect>::ConstIterator it = rects.begin(); it != rects.end(); ++it)
+                [results addObject:[NSValue valueWithRect:*it]];
+        }
+        return [results autorelease];
+    }
+    return nil;
+}
+
 @end
 
 @implementation DOMNode (WebCoreInternal)
@@ -1436,6 +1459,16 @@ static ListenerMap *listenerMap;
     [self _elementImpl]->blur();
 }
 
+- (void)scrollIntoView:(BOOL)alignTop
+{
+    [self _elementImpl]->scrollIntoView(alignTop);
+}
+
+- (void)scrollIntoViewIfNeeded:(BOOL)centerIfNeeded
+{
+    [self _elementImpl]->scrollIntoViewIfNeeded(centerIfNeeded);
+}
+
 @end
 
 @implementation DOMElement (WebCoreInternal)
index 5a8a4180efe20b29abac09780529770ef30df04c..f37312434a7b659dd24f3f469f0c26da23c34809 100644 (file)
@@ -32,7 +32,9 @@
 @class DOMElement;
 @class DOMNamedNodeMap;
 @class DOMNodeList;
+@class DOMEvent;
 
+@protocol DOMEventListener;
 @protocol DOMEventTarget;
 
 typedef struct DOMObjectInternal DOMObjectInternal;
index e3d919b539b4ac74070b692e57301bb4e5e0fecc..c6417e3b384ecbc74faa61571845f1cf67400c46 100644 (file)
 - (DOMCSSStyleDeclaration *)createCSSStyleDeclaration;
 @end
 
-@interface DOMElement (DOMElementExtensions)
-- (void)focus;
-- (void)blur;
-@end
-
 @interface DOMHTMLElement (DOMHTMLElementExtensions)
 - (NSString *)innerHTML;
 - (void)setInnerHTML:(NSString *)innerHTML;
index ae148bc4e233041db901863c13bd99ef68166430..35e4f67fcd8761c8a9f13e6170eae2b6b6a12eb0 100644 (file)
 - (NSString *)getPropertyShorthand:(NSString *)propertyName;
 - (BOOL)isPropertyImplicit:(NSString *)propertyName;
 @end
+
+@interface DOMNode (DOMNodePendingPublic)
+- (BOOL)isSameNode:(DOMNode *) other;
+- (BOOL)isEqualNode:(DOMNode *) other;
+
+- (NSRect)boundingBox;
+- (NSArray *)lineBoxRects;
+
+- (NSString *)textContent;
+- (void)setTextContent:(NSString *)text;
+
+- (void)addEventListener:(NSString *)type :(id <DOMEventListener>)listener :(BOOL)useCapture;
+- (void)removeEventListener:(NSString *)type :(id <DOMEventListener>)listener :(BOOL)useCapture;
+- (BOOL)dispatchEvent:(DOMEvent *)event;
+@end
+
+@interface DOMElement (DOMElementExtensions)
+- (void)focus;
+- (void)blur;
+- (void)scrollIntoView:(BOOL)alignTop;
+- (void)scrollIntoViewIfNeeded:(BOOL)centerIfNeeded;
+@end
 // END
 
 // Pending DOM3 APIs
index 4f17bcdce71060a11aec47a837f8c5bf95cb62f9..ffbb2e460166965955cbb8f8c412e85c43f057a8 100644 (file)
@@ -1,3 +1,156 @@
+2006-01-15  Timothy Hatcher  <timothy@apple.com>
+
+        Reviewed by Darin.
+        New DOM Inspector that lives in WebKit and is accessible from any WebView.
+        Accessible from a contextual menu when the WebKitEnableInspectElementContextMenuItem default is
+        true or you have a development build. Browsing the tree, serialized HTML and CSS rules work.
+        To always enable enter the following in the Terminal (change the bundle id to affect other WebKit apps):
+        defaults write com.apple.Safari WebKitEnableInspectElementContextMenuItem -bool true
+        http://bugzilla.opendarwin.org/show_bug.cgi?id=6571
+
+        * English.lproj/Localizable.strings:
+        * English.lproj/StringsNotToBeLocalized.txt: reorder of the entries
+        * Misc.subproj/WebKitNSStringExtras.h:
+        * Misc.subproj/WebKitNSStringExtras.m:
+        (-[NSString _webkit_stringByCollapsingWhitespaceCharacters]): collapses consecutive whitespace into a single space
+        * WebCoreSupport.subproj/WebFrameBridge.m:
+        (-[WebFrameBridge pluginViewWithPackage:attributeNames:attributeValues:baseURL:]): cleanup
+        (-[WebFrameBridge viewForPluginWithURL:attributeNames:attributeValues:MIMEType:]): call the new UI delegate method
+        * WebInspector.subproj: Added.
+        * WebInspector.subproj/WebInspector.h: Added.
+        * WebInspector.subproj/WebInspector.m: Added.
+        (+[WebInspector sharedWebInspector]):
+        (-[WebInspector init]):
+        (-[WebInspector initWithWebFrame:]):
+        (-[WebInspector dealloc]):
+        (-[WebInspector window]):
+        (-[WebInspector windowDidLoad]):
+        (-[WebInspector windowWillClose:]):
+        (-[WebInspector showWindow:]):
+        (-[WebInspector setWebFrame:]):
+        (-[WebInspector webFrame]):
+        (-[WebInspector setRootDOMNode:]):
+        (-[WebInspector rootDOMNode]):
+        (-[WebInspector setFocusedDOMNode:]):
+        (-[WebInspector focusedDOMNode]):
+        (-[WebInspector setSearchQuery:]):
+        (-[WebInspector searchQuery]):
+        (-[WebInspector searchResults]):
+        (-[WebInspector showOptionsMenu]):
+        (-[WebInspector selectNewRoot:]):
+        (-[WebInspector resizeTopArea:]):
+        (-[WebInspector treeViewScrollTo:]):
+        (-[WebInspector treeViewOffsetTop]):
+        (-[WebInspector treeViewScrollHeight]):
+        (-[WebInspector traverseTreeBackward]):
+        (-[WebInspector traverseTreeForward]):
+        (-[WebInspector _toggleIgnoreWhitespace:]):
+        (-[WebInspector _highlightNode:]):
+        (-[WebInspector _nodeHighlightExpired:]):
+        (-[WebInspector _focusRootNode:]):
+        (-[WebInspector _revealAndSelectNodeInTree:]):
+        (-[WebInspector _showSearchResults:]):
+        (-[WebInspector _refreshSearch]):
+        (-[WebInspector _update]):
+        (-[WebInspector _updateRoot]):
+        (-[WebInspector _updateTreeScrollbar]):
+        (+[WebInspector isSelectorExcludedFromWebScript:]):
+        (+[WebInspector webScriptNameForSelector:]):
+        (+[WebInspector isKeyExcludedFromWebScript:]):
+        (-[WebInspector handleEvent:]):
+        (-[WebInspector webView:didFinishLoadForFrame:]):
+        (-[WebInspector webView:plugInViewWithArguments:]):
+        (-[WebInspector outlineView:numberOfChildrenOfItem:]):
+        (-[WebInspector outlineView:isItemExpandable:]):
+        (-[WebInspector outlineView:child:ofItem:]):
+        (-[WebInspector outlineView:objectValueForTableColumn:byItem:]):
+        (-[WebInspector outlineView:willDisplayOutlineCell:forTableColumn:item:]):
+        (-[WebInspector outlineViewItemDidCollapse:]):
+        (-[WebInspector outlineViewSelectionDidChange:]):
+        (-[WebInspectorPrivate dealloc]):
+        (-[DOMHTMLElement _addClassName:]): Helper method for the Inspector to append style classes
+        (-[DOMHTMLElement _removeClassName:]): Helper method for the Inspector to remove style classes
+        (-[DOMNode _contentPreview]):
+        (-[DOMNode _isAncestorOfNode:]):
+        (-[DOMNode _isDescendantOfNode:]):
+        (-[DOMNode _isWhitespace]):
+        (-[DOMNode _lengthOfChildNodesIgnoringWhitespace]):
+        (-[DOMNode _childNodeAtIndexIgnoringWhitespace:]):
+        (-[DOMNode _nextSiblingSkippingWhitespace]):
+        (-[DOMNode _previousSiblingSkippingWhitespace]):
+        (-[DOMNode _firstChildSkippingWhitespace]):
+        (-[DOMNode _lastChildSkippingWhitespace]):
+        (-[DOMNode _firstAncestorCommonWithNode:]):
+        (-[DOMNode _traverseNextNodeStayingWithin:]):
+        (-[DOMNode _traverseNextNodeSkippingWhitespaceStayingWithin:]):
+        (-[DOMNode _traversePreviousNode]):
+        (-[DOMNode _traversePreviousNodeSkippingWhitespace]):
+        (-[DOMNode _nodeTypeName]):
+        (-[DOMNode _shortDisplayName]):
+        (-[DOMNode _displayName]):
+        * WebInspector.subproj/WebInspectorInternal.h: Added.
+        * WebInspector.subproj/WebInspectorOutlineView.h: Added.
+        * WebInspector.subproj/WebInspectorOutlineView.m: Added.
+        (-[WebInspectorOutlineView isOpaque]):
+        (-[WebInspectorOutlineView _highlightColorForCell:]):
+        (-[WebInspectorOutlineView _highlightRow:clipRect:]):
+        (-[WebInspectorOutlineView drawBackgroundInClipRect:]):
+        * WebInspector.subproj/WebInspectorPanel.h: Added.
+        * WebInspector.subproj/WebInspectorPanel.m: Added.
+        (-[WebInspectorPanel canBecomeKeyWindow]):
+        (-[WebInspectorPanel canBecomeMainWindow]):
+        (-[WebInspectorPanel moveWindow:]):
+        (-[WebInspectorPanel resizeWindow:]):
+        (-[WebInspectorPanel sendEvent:]):
+        * WebInspector.subproj/WebNodeHighlight.h: Added.
+        * WebInspector.subproj/WebNodeHighlight.m: Added.
+        (-[WebNodeHighlight initWithBounds:andRects:forView:]):
+        (-[WebNodeHighlight dealloc]):
+        (-[WebNodeHighlight fractionComplete]):
+        (-[WebNodeHighlight expire]):
+        (-[WebNodeHighlight redraw:]):
+        * WebInspector.subproj/WebNodeHighlightView.h: Added.
+        * WebInspector.subproj/WebNodeHighlightView.m: Added.
+        (-[WebNodeHighlightView roundedRect:withRadius:]):
+        (-[WebNodeHighlightView initWithHighlight:andRects:forView:]):
+        (-[WebNodeHighlightView dealloc]):
+        (-[WebNodeHighlightView isOpaque]):
+        (-[WebNodeHighlightView drawRect:]):
+        * WebInspector.subproj/webInspector: Added.
+        * WebInspector.subproj/webInspector/Images: Added.
+        * WebInspector.subproj/webInspector/Images/close.png: Added.
+        * WebInspector.subproj/webInspector/Images/closePressed.png: Added.
+        * WebInspector.subproj/webInspector/Images/downTriangle.png: Added.
+        * WebInspector.subproj/webInspector/Images/menu.png: Added.
+        * WebInspector.subproj/webInspector/Images/menuPressed.png: Added.
+        * WebInspector.subproj/webInspector/Images/popupFill.png: Added.
+        * WebInspector.subproj/webInspector/Images/popupFillPressed.png: Added.
+        * WebInspector.subproj/webInspector/Images/popupLeft.png: Added.
+        * WebInspector.subproj/webInspector/Images/popupLeftPressed.png: Added.
+        * WebInspector.subproj/webInspector/Images/popupRight.png: Added.
+        * WebInspector.subproj/webInspector/Images/popupRightPressed.png: Added.
+        * WebInspector.subproj/webInspector/Images/rightTriangle.png: Added.
+        * WebInspector.subproj/webInspector/Images/scrollThumbBottom.png: Added.
+        * WebInspector.subproj/webInspector/Images/scrollThumbMiddle.png: Added.
+        * WebInspector.subproj/webInspector/Images/scrollThumbTop.png: Added.
+        * WebInspector.subproj/webInspector/Images/scrollTrackBottom.png: Added.
+        * WebInspector.subproj/webInspector/Images/scrollTrackMiddle.png: Added.
+        * WebInspector.subproj/webInspector/Images/scrollTrackTop.png: Added.
+        * WebInspector.subproj/webInspector/Images/squareButtonRight.png: Added.
+        * WebInspector.subproj/webInspector/Images/squareButtonRightPressed.png: Added.
+        * WebInspector.subproj/webInspector/Images/upTriangle.png: Added.
+        * WebInspector.subproj/webInspector/inspector.css: Added.
+        * WebInspector.subproj/webInspector/inspector.html: Added.
+        * WebInspector.subproj/webInspector/inspector.js: Added.
+        * WebKit.xcodeproj/project.pbxproj: Adds Web Inspector files
+        * WebView.subproj/WebUIDelegatePrivate.h: new UI delegate method to supply a replacement view for plugins
+        * WebView.subproj/WebView.m:
+        (-[WebView _menuForElement:defaultItems:]): Add a new context menu item for inspecting
+        (-[WebView _inspectElement:]): Context menu item target for inspecting
+
 2006-01-14  Alexey Proskuryakov  <ap@nypop.com>
 
         Reviewed by Darin.
index 2b8308074c3fda357786684432cdcb48d7ebcdff..2605601067e2e02fc08524ce8662cae3b945e838 100644 (file)
Binary files a/WebKit/English.lproj/Localizable.strings and b/WebKit/English.lproj/Localizable.strings differ
index e87e16377f2f11329f208bdd8a08effb70ff4664..cbd9e330d843d80941a3b03e8542f4c2140baa6b 100644 (file)
@@ -435,9 +435,9 @@ Plugins.subproj/WebBasePluginPackage.m:"name: %@\npath: %@\nmimeTypes:\n%@\nplug
 Plugins.subproj/WebNetscapePluginPackage.m:"RealPlayer Plugin"
 Plugins.subproj/WebNetscapePluginPackage.m:"main"
 Plugins.subproj/WebPluginDocumentView.m:"type"
+WebCoreSupport.subproj/WebCookieAdapter.m:"Cookie"
 WebCoreSupport.subproj/WebFrameBridge.m:"height"
 WebCoreSupport.subproj/WebFrameBridge.m:"width"
-WebCoreSupport.subproj/WebCookieAdapter.m:"Cookie"
 WebCoreSupport.subproj/WebImageData.m:"Gray"
 WebCoreSupport.subproj/WebImageData.m:"RGB"
 WebCoreSupport.subproj/WebImageRendererFactory.m:"clear"
index 9f9bd74e2cacadea1b16764fcb3fd903bf707770..d7fe47ce7133335188ffd2602bfa5396eecfe32c 100644 (file)
@@ -51,6 +51,7 @@
 
 - (NSString *)_webkit_stringByTrimmingWhitespace;
 - (NSString *)_webkit_stringByCollapsingNonPrintingCharacters;
+- (NSString *)_webkit_stringByCollapsingWhitespaceCharacters;
 - (NSString *)_webkit_fixedCarbonPOSIXPath;
 
 @end
index cec1068972c3048536066211e64bcde6645a4df2..9f46820b35405929ec9000c49d3e4da0b8e19278 100644 (file)
@@ -303,6 +303,38 @@ static BOOL canUseFastRenderer(const UniChar *buffer, unsigned length)
     return result;
 }
 
+- (NSString *)_webkit_stringByCollapsingWhitespaceCharacters
+{
+    NSMutableString *result = [[NSMutableString alloc] initWithCapacity:[self length]];
+    NSCharacterSet *spaces = [NSCharacterSet whitespaceAndNewlineCharacterSet];
+    static NSCharacterSet *notSpaces = nil;
+
+    if (notSpaces == nil)
+        notSpaces = [[spaces invertedSet] retain];
+
+    unsigned length = [self length];
+    unsigned position = 0;
+    while (position != length) {
+        NSRange nonSpace = [self rangeOfCharacterFromSet:notSpaces options:0 range:NSMakeRange(position, length - position)];
+        if (nonSpace.location == NSNotFound)
+            break;
+
+        NSRange space = [self rangeOfCharacterFromSet:spaces options:0 range:NSMakeRange(nonSpace.location, length - nonSpace.location)];
+        if (space.location == NSNotFound)
+            space.location = length;
+
+        if (space.location > nonSpace.location) {
+            if (position != 0)
+                [result appendString:@" "];
+            [result appendString:[self substringWithRange:NSMakeRange(nonSpace.location, space.location - nonSpace.location)]];
+        }
+
+        position = space.location;
+    }
+
+    return [result autorelease];
+}
+
 -(NSString *)_webkit_fixedCarbonPOSIXPath
 {
     NSFileManager *fileManager = [NSFileManager defaultManager];
index b6b406768f031955d35f5288ca1e228e5318570d..c8330ced32ca204c158deefa4f8708a97225aea3 100644 (file)
@@ -902,12 +902,7 @@ NSString *WebPluginContainerKey =   @"WebPluginContainer";
     WebPluginController *pluginController = [docView _pluginController];
     
     // Store attributes in a dictionary so they can be passed to WebPlugins.
-    NSMutableDictionary *attributes = [[NSMutableDictionary alloc] init];
-    unsigned count = [attributeNames count];
-    unsigned i;
-    for (i = 0; i < count; i++) {
-        [attributes setObject:[attributeValues objectAtIndex:i] forKey:[attributeNames objectAtIndex:i]];
-    }    
+    NSMutableDictionary *attributes = [[NSMutableDictionary alloc] initWithObjects:attributeValues forKeys:attributeNames];
     
     [pluginPackage load];
     Class viewFactory = [pluginPackage viewFactory];
@@ -931,7 +926,7 @@ NSString *WebPluginContainerKey =   @"WebPluginContainer";
             nil];
         LOG(Plugins, "arguments:\n%@", arguments);
     }
-    
+
     view = [WebPluginController plugInViewWithArguments:arguments fromPluginPackage:pluginPackage];
     
     [attributes release];
@@ -964,7 +959,23 @@ NSString *WebPluginContainerKey =   @"WebPluginContainer";
     WebBasePluginPackage *pluginPackage = nil;
     NSView *view = nil;
     int errorCode = 0;
-    
+
+    WebView *wv = [_frame webView];
+    id wd = [wv UIDelegate];
+
+    if ([wd respondsToSelector:@selector(webView:plugInViewWithArguments:)]) {
+        NSMutableDictionary *attributes = [[NSMutableDictionary alloc] initWithObjects:attributeValues forKeys:attributeNames];
+        NSDictionary *arguments = [NSDictionary dictionaryWithObjectsAndKeys:
+            attributes, WebPlugInAttributesKey,
+            [NSNumber numberWithInt:WebPlugInModeEmbed], WebPlugInModeKey,
+            URL, WebPlugInBaseURLKey, // URL might be nil, so add it last
+            nil];
+        [attributes release];
+        view = [wd webView:wv plugInViewWithArguments:arguments];
+        if (view)
+            return view;
+    }
+
     if ([MIMEType length] != 0) {
         pluginPackage = [[WebPluginDatabase installedPlugins] pluginForMIMEType:MIMEType];
     } else {
diff --git a/WebKit/WebInspector.subproj/WebInspector.h b/WebKit/WebInspector.subproj/WebInspector.h
new file mode 100644 (file)
index 0000000..adc2996
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <AppKit/NSWindowController.h>
+
+@class WebFrame;
+@class WebInspectorPrivate;
+@class DOMNode;
+
+@interface WebInspector : NSWindowController
+{
+@private
+    WebInspectorPrivate *_private;
+}
++ (WebInspector *)sharedWebInspector;
+
+- (id)initWithWebFrame:(WebFrame *)webFrame;
+
+- (void)setWebFrame:(WebFrame *)webFrame;
+- (WebFrame *)webFrame;
+
+- (void)setRootDOMNode:(DOMNode *)node;
+- (DOMNode *)rootDOMNode;
+
+- (void)setFocusedDOMNode:(DOMNode *)node;
+- (DOMNode *)focusedDOMNode;
+
+- (void)setSearchQuery:(NSString *)query;
+- (NSString *)searchQuery;
+
+- (NSArray *)searchResults;
+@end
diff --git a/WebKit/WebInspector.subproj/WebInspector.m b/WebKit/WebInspector.subproj/WebInspector.m
new file mode 100644 (file)
index 0000000..ddf4276
--- /dev/null
@@ -0,0 +1,1300 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <WebKit/WebView.h>
+#import <WebKit/WebViewPrivate.h>
+#import <WebKit/WebHTMLView.h>
+#import <WebKit/WebFrame.h>
+#import <WebKit/DOMCore.h>
+#import <WebKit/DOMEvents.h>
+#import <WebKit/DOMHTML.h>
+#import <WebKit/DOMCSS.h>
+#import <WebKit/DOMTraversal.h>
+#import <WebKit/DOMExtensions.h>
+#import <WebKit/DOMPrivate.h>
+#import <WebKit/WebInspector.h>
+#import <WebKit/WebInspectorInternal.h>
+#import <WebKit/WebLocalizableStrings.h>
+
+#import "WebKitNSStringExtras.h"
+#import "WebNodeHighlight.h"
+#import "WebInspectorPanel.h"
+#import "WebInspectorOutlineView.h"
+
+static NSMapTable *lengthIgnoringWhitespaceCache = NULL;
+static NSMapTable *lastChildIndexIgnoringWhitespaceCache = NULL;
+static NSMapTable *lastChildIgnoringWhitespaceCache = NULL;
+
+@implementation WebInspector
++ (WebInspector *)sharedWebInspector
+{
+    static WebInspector *_sharedWebInspector = nil;
+    if (!_sharedWebInspector) {
+        _sharedWebInspector = [[self alloc] initWithWebFrame:nil];
+        _sharedWebInspector->_private->isSharedInspector = YES;
+    }
+    return _sharedWebInspector;
+}
+
+#pragma mark -
+
+- (id)init
+{
+    if (![super initWithWindow:nil])
+        return nil;
+
+    [self setWindowFrameAutosaveName:@"Web Inspector"];
+
+    _private = [[WebInspectorPrivate alloc] init];
+    _private->ignoreWhitespace = YES;
+
+    return self;
+}
+
+- (id)initWithWebFrame:(WebFrame *)webFrame
+{
+    if (![self init])
+        return nil;
+    [self setWebFrame:webFrame];
+    return self;
+}
+
+- (void)dealloc
+{
+    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"WebNodeHighlightExpired" object:nil];
+    [_private release];
+    [super dealloc];
+}
+
+#pragma mark -
+
+- (NSWindow *)window
+{
+    NSWindow *window = [super window];
+    if (!window) {
+        NSPanel *window = [[WebInspectorPanel alloc] initWithContentRect:NSMakeRect(60.0, 200.0, 350.0, 550.0) styleMask:(NSBorderlessWindowMask | NSUtilityWindowMask) backing:NSBackingStoreBuffered defer:YES];
+        [window setBackgroundColor:[NSColor clearColor]];
+        [window setOpaque:NO];
+        [window setHasShadow:YES];
+        [window _setContentHasShadow:NO];
+        [window setWorksWhenModal:YES];
+        [window setAcceptsMouseMovedEvents:YES];
+        [window setIgnoresMouseEvents:NO];
+        [window setFloatingPanel:YES];
+        [window setReleasedWhenClosed:YES];
+        [window setMovableByWindowBackground:YES];
+        [window setDelegate:self];
+        [window setMinSize:NSMakeSize(280.0, 450.0)];
+        [window setMaxSize:NSMakeSize(600.0, 700.0)];
+
+        _private->webView = [[WebView alloc] initWithFrame:[[window contentView] frame] frameName:nil groupName:nil];
+        [_private->webView setFrameLoadDelegate:self];
+        [_private->webView setUIDelegate:self];
+        [_private->webView setDrawsBackground:NO];
+        [_private->webView _setDashboardBehavior:WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows to:YES];
+        [_private->webView _setDashboardBehavior:WebDashboardBehaviorAlwaysAcceptsFirstMouse to:YES];
+        [[_private->webView windowScriptObject] setValue:self forKey:@"Inspector"];
+
+        [window setContentView:_private->webView];
+
+        NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"inspector" ofType:@"html" inDirectory:@"webInspector"];
+        [[_private->webView mainFrame] loadRequest:[[[NSURLRequest alloc] initWithURL:[NSURL fileURLWithPath:path]] autorelease]];
+
+        [self setWindow:window];
+        [self windowDidLoad];
+        return window;
+    }
+
+    return window;
+}
+
+- (void)windowDidLoad
+{
+    if (_private->windowLoaded)
+        return;
+    _private->windowLoaded = YES;
+
+    _private->rightArrowImage = [[NSImage alloc] initWithContentsOfFile:[[NSBundle bundleForClass:[self class]] pathForResource:@"rightTriangle" ofType:@"png" inDirectory:@"webInspector/Images"]];
+    _private->downArrowImage = [[NSImage alloc] initWithContentsOfFile:[[NSBundle bundleForClass:[self class]] pathForResource:@"downTriangle" ofType:@"png" inDirectory:@"webInspector/Images"]];
+
+    if ([_private->searchQuery length]) {
+        [self _showSearchResults:YES];
+        [self _refreshSearch];
+    }
+
+    [self performSelector:@selector(_highlightNode:) withObject:_private->focusedNode afterDelay:0.0];
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_nodeHighlightExpired:) name:@"WebNodeHighlightExpired" object:nil];
+}
+
+- (void)windowWillClose:(NSNotification *)notification
+{
+    if (!_private->isSharedInspector)
+        [self release];
+}
+
+- (IBAction)showWindow:(id)sender
+{
+    [self _update];
+    [super showWindow:sender];
+}
+
+#pragma mark -
+
+- (void)setWebFrame:(WebFrame *)webFrame
+{
+    if ([webFrame isEqual:_private->webFrame])
+        return;
+
+    [webFrame retain];
+    [_private->webFrame release];
+    _private->webFrame = webFrame;
+
+    [self setFocusedDOMNode:[webFrame DOMDocument]];
+}
+
+- (WebFrame *)webFrame
+{
+    return _private->webFrame;
+}
+
+#pragma mark -
+
+- (void)setRootDOMNode:(DOMNode *)node
+{
+    if (![node hasChildNodes] || [node isSameNode:_private->rootNode])
+        return;
+
+    [node retain];
+    [_private->rootNode release];
+    _private->rootNode = node;
+
+    [self _updateRoot];
+}
+
+- (DOMNode *)rootDOMNode
+{
+    return _private->rootNode;
+}
+
+#pragma mark -
+
+- (void)setFocusedDOMNode:(DOMNode *)node
+{
+    if ([node isSameNode:_private->focusedNode])
+        return;
+
+    [[NSRunLoop currentRunLoop] cancelPerformSelector:@selector(_highlightNode:) target:self argument:_private->focusedNode];
+
+    [node retain];
+    [_private->focusedNode release];
+    _private->focusedNode = node;
+
+    DOMNode *root = _private->rootNode;
+    if (!root || (![root isSameNode:node] && ![root _isAncestorOfNode:node]))
+        [self setRootDOMNode:node];
+
+    if (!_private->webViewLoaded)
+        return;
+
+    [self _revealAndSelectNodeInTree:node];
+    [self _update];
+
+    if (!_private->preventHighlight) {
+        NSRect bounds = [node boundingBox];
+        if (!NSIsEmptyRect(bounds)) {
+            NSRect visible = [[[_private->webFrame frameView] documentView] visibleRect];
+            BOOL needsScroll = !NSContainsRect(visible, bounds) && !NSContainsRect(bounds, visible);
+
+            // only scroll if the bounds isn't in the visible rect and dosen't contain the visible rect
+            if (needsScroll) {
+                // scroll to the parent element if we arn't focued on an element
+                DOMElement *element = (DOMElement *)_private->focusedNode;
+                if (![element isKindOfClass:[DOMElement class]])
+                    element = (DOMElement *)[element parentNode];
+
+                if ([element isKindOfClass:[DOMElement class]])
+                    [element scrollIntoViewIfNeeded:YES];
+
+                // give time for the scroll to happen
+                [self performSelector:@selector(_highlightNode:) withObject:node afterDelay:0.25];
+            } else
+                [self _highlightNode:node];
+        } else
+            [_private->currentHighlight expire];
+    }
+}
+
+- (DOMNode *)focusedDOMNode
+{
+    return _private->focusedNode;
+}
+
+#pragma mark -
+
+- (void)setSearchQuery:(NSString *)query
+{
+    if ([query isEqualToString:_private->searchQuery])
+        return;
+
+    [query retain];
+    [_private->searchQuery release];
+    _private->searchQuery = query;
+
+    if (_private->webViewLoaded) {
+        DOMHTMLInputElement *search = (DOMHTMLInputElement *)[_private->domDocument getElementById:@"search"];
+        [search setValue:(query ? query : @"")];
+        [self _showSearchResults:([query length] ? YES : NO)];
+        [self _refreshSearch];
+    }
+}
+
+- (NSString *)searchQuery
+{
+    return _private->searchQuery;
+}
+
+#pragma mark -
+
+- (NSArray *)searchResults
+{
+    return [NSArray arrayWithArray:_private->searchResults];
+}
+@end
+
+#pragma mark -
+
+@implementation WebInspector (WebInspectorScripting)
+- (void)showOptionsMenu
+{
+    NSMenu *menu = [[NSMenu alloc] init];
+    [menu setAutoenablesItems:NO];
+
+    NSMenuItem *item = [[[NSMenuItem alloc] init] autorelease];
+    [item setTitle:@"Ignore Whitespace"];
+    [item setTarget:self];
+    [item setAction:@selector(_toggleIgnoreWhitespace:)];
+    [item setState:_private->ignoreWhitespace];
+    [menu addItem:item];
+
+    [NSMenu popUpContextMenu:menu withEvent:[[self window] currentEvent] forView:_private->webView];
+    [menu release];
+
+    // hack to force a layout and balance mouse events
+    NSEvent *currentEvent = [[self window] currentEvent];
+    NSEvent *event = [NSEvent mouseEventWithType:NSLeftMouseUp location:[currentEvent locationInWindow] modifierFlags:[currentEvent modifierFlags] timestamp:[currentEvent timestamp] windowNumber:[[currentEvent window] windowNumber] context:[currentEvent context] eventNumber:[currentEvent eventNumber] clickCount:[currentEvent clickCount] pressure:[currentEvent pressure]];
+    [[[[_private->webView mainFrame] frameView] documentView] mouseUp:event];
+}
+
+- (void)selectNewRoot:(DOMHTMLSelectElement *)popup
+{
+    unsigned index = [popup selectedIndex];
+    unsigned count = 0;
+
+    DOMNode *currentNode = _private->rootNode;
+    while (currentNode) {
+        if (count == index) {
+            [self setRootDOMNode:currentNode];
+            break;
+        }
+        count++;
+        currentNode = [currentNode parentNode];
+    }
+}
+
+- (void)resizeTopArea:(DOMEvent *)domEvent
+{
+    NSWindow *window = [self window];
+    NSEvent *event = [window currentEvent];
+    NSPoint lastLocation = [window convertBaseToScreen:[event locationInWindow]];
+    NSRect lastFrame = [window frame];
+    NSSize minSize = [window minSize];
+    NSSize maxSize = [window maxSize];
+    BOOL mouseUpOccurred = NO;
+
+    DOMHTMLElement *topArea = (DOMHTMLElement *)[_private->domDocument getElementById:@"top"];
+    DOMHTMLElement *splitter = (DOMHTMLElement *)[_private->domDocument getElementById:@"splitter"];
+    DOMHTMLElement *bottomArea = (DOMHTMLElement *)[_private->domDocument getElementById:@"bottom"];
+
+    while (!mouseUpOccurred) {
+        // set mouseUp flag here, but process location of event before exiting from loop, leave mouseUp in queue
+        event = [window nextEventMatchingMask:(NSLeftMouseDraggedMask | NSLeftMouseUpMask) untilDate:[NSDate distantFuture] inMode:NSEventTrackingRunLoopMode dequeue:YES];
+
+        if ([event type] == NSLeftMouseUp)
+            mouseUpOccurred = YES;
+
+        NSPoint newLocation = [window convertBaseToScreen:[event locationInWindow]];
+        if (NSEqualPoints(newLocation, lastLocation))
+            continue;
+
+        NSRect proposedRect = lastFrame;
+        long delta = newLocation.y - lastLocation.y;
+        proposedRect.size.height -= delta;
+        proposedRect.origin.y += delta;
+
+        if (proposedRect.size.height < minSize.height) {
+            proposedRect.origin.y -= minSize.height - proposedRect.size.height;
+            proposedRect.size.height = minSize.height;
+        } else if (proposedRect.size.height > maxSize.height) {
+            proposedRect.origin.y -= maxSize.height - proposedRect.size.height;
+            proposedRect.size.height = maxSize.height;
+        }
+
+        NSNumber *baseValue = [topArea valueForKey:@"offsetHeight"];
+        NSString *newValue = [NSString stringWithFormat:@"%dpx", [baseValue unsignedLongValue] - delta];
+        [[topArea style] setProperty:@"height" :newValue :@""];
+
+        baseValue = [splitter valueForKey:@"offsetTop"];
+        newValue = [NSString stringWithFormat:@"%dpx", [baseValue unsignedLongValue] - delta];
+        [[splitter style] setProperty:@"top" :newValue :@""];
+
+        baseValue = [bottomArea valueForKey:@"offsetTop"];
+        newValue = [NSString stringWithFormat:@"%dpx", [baseValue unsignedLongValue] - delta];
+        [[bottomArea style] setProperty:@"top" :newValue :@""];
+
+        [window setFrame:proposedRect display:YES];
+        lastLocation = newLocation;
+        lastFrame = proposedRect;
+
+        [self _updateTreeScrollbar];
+    }
+
+    // post the mouse up event back to the queue so the WebView can get it
+    [window postEvent:event atStart:YES];
+}
+
+- (void)treeViewScrollTo:(float)number
+{
+    float bottom = NSHeight([_private->treeOutlineView frame]) - NSHeight([_private->treeScrollView documentVisibleRect]);
+    number = MAX(0.0, MIN(bottom, number));
+    [[_private->treeScrollView contentView] scrollToPoint:NSMakePoint(0.0, number)];
+}
+
+- (float)treeViewOffsetTop
+{
+    return NSMinY([_private->treeScrollView documentVisibleRect]);
+}
+
+- (float)treeViewScrollHeight
+{
+    return NSHeight([_private->treeOutlineView frame]);
+}
+
+- (void)traverseTreeBackward
+{
+    if (_private->searchResultsVisible) {
+        // if we have a search showing, we will only walk up and down the results
+        int row = [_private->treeOutlineView selectedRow];
+        if (row == -1)
+            return;
+        if ((row - 1) >= 0) {
+            row--;
+            [_private->treeOutlineView selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO];
+            [_private->treeOutlineView scrollRowToVisible:row];
+        }
+        return;
+    }
+
+    DOMNode *node =  nil;
+    // traverse backward, holding opton will traverse only to the previous sibling
+    if ([[[self window] currentEvent] modifierFlags] & NSAlternateKeyMask) {
+        if (!_private->ignoreWhitespace)
+            node = [_private->focusedNode previousSibling];
+        else
+            node = [_private->focusedNode _previousSiblingSkippingWhitespace];
+    } else {
+        if (!_private->ignoreWhitespace)
+            node = [_private->focusedNode _traversePreviousNode];
+        else
+            node = [_private->focusedNode _traversePreviousNodeSkippingWhitespace];
+    }
+
+    if (node) {
+        DOMNode *root = _private->rootNode;
+        if (![root isSameNode:node] && ![root _isAncestorOfNode:node])
+            [self setRootDOMNode:[_private->focusedNode _firstAncestorCommonWithNode:node]];
+        [self setFocusedDOMNode:node];
+    }
+}
+
+- (void)traverseTreeForward
+{
+    if (_private->searchResultsVisible) {
+        // if we have a search showing, we will only walk up and down the results
+        int row = [_private->treeOutlineView selectedRow];
+        if (row == -1)
+            return;
+        if ((row + 1) < (int)[_private->searchResults count]) {
+            row++;
+            [_private->treeOutlineView selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO];
+            [_private->treeOutlineView scrollRowToVisible:row];
+        }
+        return;
+    }
+
+    DOMNode *node =  nil;
+    // traverse forward, holding opton will traverse only to the next sibling
+    if ([[[self window] currentEvent] modifierFlags] & NSAlternateKeyMask) {
+        if (!_private->ignoreWhitespace)
+            node = [_private->focusedNode nextSibling];
+        else
+            node = [_private->focusedNode _nextSiblingSkippingWhitespace];
+    } else {
+        if (!_private->ignoreWhitespace)
+            node = [_private->focusedNode _traverseNextNodeStayingWithin:nil];
+        else
+            node = [_private->focusedNode _traverseNextNodeSkippingWhitespaceStayingWithin:nil];
+    }
+
+    if (node) {
+        DOMNode *root = _private->rootNode;
+        if (![root isSameNode:node] && ![root _isAncestorOfNode:node])
+            [self setRootDOMNode:[_private->focusedNode _firstAncestorCommonWithNode:node]];
+        [self setFocusedDOMNode:node];
+    }
+}
+@end
+
+#pragma mark -
+
+@implementation WebInspector (WebInspectorPrivate)
+- (IBAction)_toggleIgnoreWhitespace:(id)sender
+{
+    _private->ignoreWhitespace = !_private->ignoreWhitespace;
+    [_private->treeOutlineView reloadData];
+}
+
+- (void)_highlightNode:(DOMNode *)node
+{
+    if (_private->currentHighlight) {
+        [_private->currentHighlight expire];
+        [_private->currentHighlight release];
+        _private->currentHighlight = nil;
+    }
+
+    NSView *view = [[_private->webFrame frameView] documentView];
+    NSRect bounds = NSIntersectionRect([node boundingBox], [view visibleRect]);
+    if (!NSIsEmptyRect(bounds)) {
+        NSArray *rects = nil;
+        if ([node isKindOfClass:[DOMElement class]]) {
+            DOMCSSStyleDeclaration *style = [_private->domDocument getComputedStyle:(DOMElement *)node :@""];
+            if ([[style getPropertyValue:@"display"] isEqualToString:@"inline"])
+                rects = [node lineBoxRects];
+        } else if ([node isKindOfClass:[DOMText class]])
+            rects = [node lineBoxRects];
+
+        if (![rects count])
+            rects = [NSArray arrayWithObject:[NSValue valueWithRect:bounds]];
+
+        _private->currentHighlight = [[WebNodeHighlight alloc] initWithBounds:bounds andRects:rects forView:view];
+    }
+}
+
+- (void)_nodeHighlightExpired:(NSNotification *)notification
+{
+    if (_private->currentHighlight == [notification object]) {
+        [_private->currentHighlight release];
+        _private->currentHighlight = nil;
+    }
+}
+
+- (void)_focusRootNode:(id)sender
+{
+    id node = nil;
+    if ([sender isKindOfClass:[NSMenuItem class]]) {
+        node = [sender representedObject];
+    } else if(sender == _private->treeOutlineView) {
+        int index = [sender selectedRow];
+        if (index == -1)
+            return;
+        node = [sender itemAtRow:index];
+    }
+
+    if (![node isSameNode:_private->rootNode]) {
+        [self setRootDOMNode:node];
+        [self setSearchQuery:nil]; // exit search mode
+    }
+}
+
+- (void)_revealAndSelectNodeInTree:(DOMNode *)node
+{
+
+    if (!_private->webViewLoaded || !node)
+        return;
+
+    if (!_private->preventRevealOnFocus) {
+        NSMutableArray *ancestors = [[NSMutableArray alloc] init];
+        DOMNode *currentNode = [node parentNode];
+        while (currentNode) {
+            [ancestors addObject:currentNode];
+            if ([currentNode isSameNode:_private->rootNode])
+                break;
+            currentNode = [currentNode parentNode];
+        }
+
+        NSEnumerator *enumerator = [ancestors reverseObjectEnumerator];
+        while ((currentNode = [enumerator nextObject]))
+            [_private->treeOutlineView expandItem:currentNode];
+
+        [ancestors release];
+    }
+
+    int index = [_private->treeOutlineView rowForItem:node];
+    if (index != -1) {
+        [_private->treeOutlineView selectRowIndexes:[NSIndexSet indexSetWithIndex:index] byExtendingSelection:NO];
+        [_private->treeOutlineView scrollRowToVisible:index];
+    }
+}
+
+- (void)_showSearchResults:(BOOL)show
+{
+    if (show == _private->searchResultsVisible)
+        return;
+
+    DOMHTMLElement *treePopup = (DOMHTMLElement *)[_private->domDocument getElementById:@"treePopup"];
+    DOMHTMLElement *searchField = (DOMHTMLElement *)[_private->domDocument getElementById:@"search"];
+    DOMHTMLElement *searchCount = (DOMHTMLElement *)[_private->domDocument getElementById:@"searchCount"];
+
+    if (show) {
+        [[treePopup style] setDisplay:@"none"];
+        [[searchCount style] setDisplay:@"block"];
+        [[searchField style] setWidth:@"150px"];
+    } else {
+        [[treePopup style] removeProperty:@"display"];
+        [[searchCount style] removeProperty:@"display"];
+        [[searchField style] setWidth:@"90px"];
+    }
+
+    _private->preventRevealOnFocus = show;
+    _private->searchResultsVisible = show;
+}
+
+- (void)_refreshSearch
+{
+    if (!_private->searchResults)
+        _private->searchResults = [[NSMutableArray alloc] initWithCapacity:100];
+    else
+        [_private->searchResults removeAllObjects];
+
+    NSString *query = _private->searchQuery;
+    if (![query length]) {
+        [_private->treeOutlineView reloadData];
+        return;
+    }
+
+    BOOL matched = NO;
+    unsigned count = 0;
+    DOMNode *node = [_private->webFrame DOMDocument];
+    while ((node = [node _traverseNextNodeStayingWithin:nil])) {
+        if ([[node nodeName] _webkit_hasCaseInsensitiveSubstring:query])
+            matched = YES;
+        else if ([node nodeType] == DOM_TEXT_NODE && [[node nodeValue] _webkit_hasCaseInsensitiveSubstring:query])
+            matched = YES;
+        else if ([node isKindOfClass:[DOMHTMLElement class]] && [[(DOMHTMLElement *)node idName] _webkit_hasCaseInsensitiveSubstring:query])
+            matched = YES;
+        else if ([node isKindOfClass:[DOMHTMLElement class]] && [[(DOMHTMLElement *)node className] _webkit_hasCaseInsensitiveSubstring:query])
+            matched = YES;
+        if (matched) {
+            [_private->searchResults addObject:node];
+            count++;
+            matched = NO;
+        }
+    }
+
+    DOMHTMLElement *searchCount = (DOMHTMLElement *)[_private->domDocument getElementById:@"searchCount"];
+    if (count == 1)
+        [searchCount setInnerText:[NSString stringWithFormat:UI_STRING("1 node", "web inspector node search results count with 1 result"), count]];
+    else
+        [searchCount setInnerText:[NSString stringWithFormat:UI_STRING("%u nodes", "web inspector node search results count with zero or more than 1 results"), count]];
+
+    [_private->treeOutlineView reloadData];
+}
+
+- (void)_update
+{
+    if (!_private->webViewLoaded || !_private->focusedNode)
+        return;
+
+    [[_private->webView windowScriptObject] callWebScriptMethod:@"updatePanes" withArguments:nil];
+
+    DOMNode *node = _private->focusedNode;
+    DOMHTMLButtonElement *back = (DOMHTMLButtonElement *)[_private->domDocument getElementById:@"traverseUp"];
+    DOMHTMLButtonElement *forward = (DOMHTMLButtonElement *)[_private->domDocument getElementById:@"traverseDown"];
+    if (_private->searchResultsVisible) {
+        int row = [_private->treeOutlineView selectedRow];
+        if (row != -1) {
+            [forward setDisabled:!((row + 1) < (int)[_private->searchResults count])];
+            [back setDisabled:!((row - 1) >= 0)];
+        }
+    } else {
+        if (!_private->ignoreWhitespace)
+            node = [_private->focusedNode _traverseNextNodeStayingWithin:nil];
+        else
+            node = [_private->focusedNode _traverseNextNodeSkippingWhitespaceStayingWithin:nil];
+        [forward setDisabled:!node];
+
+        if (!_private->ignoreWhitespace)
+            node = [_private->focusedNode _traversePreviousNode];
+        else
+            node = [_private->focusedNode _traversePreviousNodeSkippingWhitespace];
+        [back setDisabled:!node];
+    }
+}
+
+- (void)_updateRoot
+{
+    if (!_private->webViewLoaded || !_private->rootNode || _private->searchResultsVisible)
+        return;
+
+    DOMHTMLElement *titleArea = (DOMHTMLElement *)[_private->domDocument getElementById:@"treePopupTitleArea"];
+    [titleArea setTextContent:[_private->rootNode _displayName]];
+
+    DOMHTMLElement *popup = (DOMHTMLElement *)[_private->domDocument getElementById:@"realTreePopup"];
+    [popup setInnerHTML:@""]; // reset the list
+
+    DOMNode *currentNode = _private->rootNode;
+    while (currentNode) {
+        DOMHTMLOptionElement *option = (DOMHTMLOptionElement *)[_private->domDocument createElement:@"option"];
+        [option setTextContent:[currentNode _displayName]];
+        [popup appendChild:option];
+        currentNode = [currentNode parentNode];
+    }
+
+    _private->preventSelectionRefocus = YES;
+    DOMNode *focusedNode = [_private->focusedNode retain];
+    [_private->treeOutlineView reloadData];
+    [_private->treeOutlineView expandItem:_private->rootNode];
+    [self _revealAndSelectNodeInTree:focusedNode];
+    [focusedNode release];
+    _private->preventSelectionRefocus = NO;
+}
+
+- (void)_updateTreeScrollbar
+{
+    [[_private->webView windowScriptObject] evaluateWebScript:@"treeScrollbar.refresh()"];
+}
+
+#pragma mark -
+
++ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector
+{
+    return NO;
+}
+
++ (NSString *)webScriptNameForSelector:(SEL)aSelector {
+    NSMutableString *name = [[NSStringFromSelector(aSelector) mutableCopy] autorelease];
+    [name replaceOccurrencesOfString:@":" withString:@"_" options:NSLiteralSearch range:NSMakeRange(0, [name length])];
+    if ([name hasSuffix:@"_"])
+        return [name substringToIndex:[name length] - 1];
+    return name;
+}
+
++ (BOOL)isKeyExcludedFromWebScript:(const char *)name
+{
+    return NO;
+}
+
+#pragma mark -
+
+- (void)handleEvent:(DOMEvent *)event
+{
+    if ([[event type] isEqualToString:@"search"] && [[event target] isKindOfClass:[DOMHTMLInputElement class]]) {
+        DOMHTMLInputElement *search = (DOMHTMLInputElement *)[event target];
+        [self setSearchQuery:[search value]];
+    }
+}
+
+- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame
+{
+    _private->webViewLoaded = YES;
+    [[sender windowScriptObject] setValue:self forKey:@"Inspector"];
+
+    [_private->domDocument release];
+    _private->domDocument = (DOMHTMLDocument *)[[[sender mainFrame] DOMDocument] retain];
+
+    [_private->domDocument addEventListener:@"search" :self :NO];
+
+    if ([[self searchQuery] length]) {
+        DOMHTMLInputElement *search = (DOMHTMLInputElement *)[_private->domDocument getElementById:@"search"];
+        [search setValue:[self searchQuery]];
+        [self _showSearchResults:YES];
+        [self _refreshSearch];
+    }
+
+    [self _update];
+    [self _updateRoot];
+    [[self window] invalidateShadow];
+}
+
+- (NSView *)webView:(WebView *)sender plugInViewWithArguments:(NSDictionary *)arguments
+{
+    NSDictionary *attributes = [arguments objectForKey:@"WebPlugInAttributesKey"];
+    if ([[attributes objectForKey:@"type"] isEqualToString:@"application/x-inspector-tree"]) {
+        if (!_private->treeOutlineView) {
+            _private->nodeCache = [[NSMutableSet alloc] init];
+            _private->treeScrollView = [[NSScrollView alloc] initWithFrame:NSMakeRect(0.0, 0.0, 250.0, 100.0)];
+            [_private->treeScrollView setDrawsBackground:NO];
+            [_private->treeScrollView setBorderType:NSNoBorder];
+            [_private->treeScrollView setVerticalScroller:NO];
+            [_private->treeScrollView setHasHorizontalScroller:NO];
+            [_private->treeScrollView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
+            [_private->treeScrollView setFocusRingType:NSFocusRingTypeNone];
+
+            _private->treeOutlineView = [[WebInspectorOutlineView alloc] initWithFrame:[_private->treeScrollView frame]];
+            [_private->treeOutlineView setHeaderView:nil];
+            [_private->treeOutlineView setAllowsMultipleSelection:NO];
+            [_private->treeOutlineView setAllowsEmptySelection:NO];
+            [_private->treeOutlineView setDelegate:self];
+            [_private->treeOutlineView setDataSource:self];
+            [_private->treeOutlineView sendActionOn:(NSLeftMouseUpMask | NSLeftMouseDownMask | NSLeftMouseDraggedMask)];
+            [_private->treeOutlineView setFocusRingType:NSFocusRingTypeNone];
+            [_private->treeOutlineView setAutoresizesOutlineColumn:NO];
+            [_private->treeOutlineView setRowHeight:15.0];
+            [_private->treeOutlineView setTarget:self];
+            [_private->treeOutlineView setDoubleAction:@selector(_focusRootNode:)];
+            [_private->treeOutlineView setIndentationPerLevel:12.0];
+            [_private->treeScrollView setDocumentView:_private->treeOutlineView];
+
+            NSCell *headerCell = [[NSCell alloc] initTextCell:@""];
+            NSCell *dataCell = [[NSCell alloc] initTextCell:@""];
+            [dataCell setFont:[NSFont systemFontOfSize:11.0]];
+
+            NSTableColumn *tableColumn = [[NSTableColumn alloc] initWithIdentifier:@"node"];
+            [tableColumn setHeaderCell:headerCell];
+            [tableColumn setDataCell:dataCell];
+            [tableColumn setMinWidth:50];
+            [tableColumn setWidth:300];
+            [tableColumn setEditable:NO];
+            [_private->treeOutlineView addTableColumn:tableColumn];
+            [_private->treeOutlineView setOutlineTableColumn:tableColumn];
+
+            [_private->treeOutlineView sizeLastColumnToFit];
+
+            [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_updateTreeScrollbar) name:NSViewFrameDidChangeNotification object:_private->treeOutlineView]; 
+        }
+
+        return [_private->treeOutlineView enclosingScrollView];
+    }
+
+    return nil;
+}
+
+#pragma mark -
+
+- (int)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
+{
+    if (outlineView == _private->treeOutlineView) {
+        if (!item && _private->searchResultsVisible)
+            return [_private->searchResults count];
+        if (!item)
+            return 1;
+        if (!_private->ignoreWhitespace)
+            return [[item childNodes] length];
+        return [item _lengthOfChildNodesIgnoringWhitespace];
+    }
+    return 0;
+}
+
+- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
+{
+    if (outlineView == _private->treeOutlineView) {
+        if (!_private->ignoreWhitespace)
+            return [item hasChildNodes];
+        return ([item _firstChildSkippingWhitespace] ? YES : NO);
+    }
+    return NO;
+}
+
+- (id)outlineView:(NSOutlineView *)outlineView child:(int)index ofItem:(id)item
+{
+    if (outlineView == _private->treeOutlineView) {
+        if (!item && _private->searchResultsVisible)
+            return [_private->searchResults objectAtIndex:index];
+        if (!item)
+            return _private->rootNode;
+        id node = nil;
+        if (!_private->ignoreWhitespace)
+            node = [[item childNodes] item:index];
+        else
+            node = [item _childNodeAtIndexIgnoringWhitespace:index];
+        if (!node)
+            return nil;
+        // cache the node because NSOutlineView assumes we hold on to it
+        // if we don't hold on to the node it will be released before the next time the NSOutlineView needs it
+        [_private->nodeCache addObject:node];
+        return node;
+    }
+    return nil;
+}
+
+- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
+{
+    if (outlineView == _private->treeOutlineView && item) {
+        NSShadow *shadow = [[NSShadow alloc] init];
+        [shadow setShadowColor:[NSColor blackColor]];
+        [shadow setShadowBlurRadius:2.0];
+        [shadow setShadowOffset:NSMakeSize(2.0,-2.0)];
+        NSMutableParagraphStyle *para = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
+        [para setLineBreakMode:NSLineBreakByTruncatingTail];
+        
+        NSDictionary *attrs = [[NSDictionary alloc] initWithObjectsAndKeys:[NSColor whiteColor], NSForegroundColorAttributeName, shadow, NSShadowAttributeName, para, NSParagraphStyleAttributeName, nil];
+        NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:[item _displayName] attributes:attrs];
+        [attrs release];
+
+        if ([item hasChildNodes] && ![outlineView isItemExpanded:item]) {
+            attrs = [[NSDictionary alloc] initWithObjectsAndKeys:[NSColor colorWithCalibratedRed:1.0 green:1.0 blue:1.0 alpha:0.5], NSForegroundColorAttributeName, shadow, NSShadowAttributeName, para, NSParagraphStyleAttributeName, nil];
+            NSAttributedString *preview = [[NSAttributedString alloc] initWithString:[item _contentPreview] attributes:attrs];
+            [string appendAttributedString:preview];
+            [attrs release];
+            [preview release];
+        }
+
+        [para release];
+        [shadow release];
+        return [string autorelease];
+    }
+
+    return nil;
+}
+
+- (void)outlineView:(NSOutlineView *)outlineView willDisplayOutlineCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
+{
+    if (outlineView == _private->treeOutlineView)
+        [cell setImage:([cell state] ? _private->downArrowImage : _private->rightArrowImage)];
+}
+
+- (void)outlineViewItemDidCollapse:(NSNotification *)notification
+{
+    if ([notification object] == _private->treeOutlineView) {
+        DOMNode *node = [[notification userInfo] objectForKey:@"NSObject"];
+        if (!node)
+            return;
+
+        // remove all child nodes from the node cache when the parent collapses
+        node = [node firstChild];
+        while (node) {
+            NSMapRemove(lengthIgnoringWhitespaceCache, node);
+            NSMapRemove(lastChildIndexIgnoringWhitespaceCache, node);
+            NSMapRemove(lastChildIgnoringWhitespaceCache, node);
+            [_private->nodeCache removeObject:node];
+            node = [node nextSibling];
+        }
+    }
+}
+
+- (void)outlineViewSelectionDidChange:(NSNotification *)notification
+{
+    if ([notification object] == _private->treeOutlineView && !_private->preventSelectionRefocus) {
+        int index = [_private->treeOutlineView selectedRow];
+        if (index == -1)
+            return;
+        [self setFocusedDOMNode:[_private->treeOutlineView itemAtRow:index]];
+        [self _updateTreeScrollbar];
+    }
+}
+@end
+
+#pragma mark -
+
+@implementation WebInspectorPrivate
+- (void)dealloc
+{
+    [webView release];
+    [domDocument release];
+    [webFrame release];
+    [rootNode release];
+    [focusedNode release];
+    [searchQuery release];
+    [nodeCache release];
+    [treeScrollView release];
+    [treeOutlineView release];
+    [matchedRules release];
+    [currentHighlight release];
+    [rightArrowImage release];
+    [downArrowImage release];
+    [super dealloc];
+}
+@end
+
+#pragma mark -
+
+@implementation DOMHTMLElement (DOMHTMLElementInspectorAdditions)
+- (void)_addClassName:(NSString *)name
+{
+    NSString *class = [self className];
+    if ([class rangeOfString:name].location != NSNotFound)
+        return;
+    if ([class length]) {
+        NSString *new = [[NSString alloc] initWithFormat:@"%@ %@", class, name];
+        [self setClassName:new];
+        [new release];
+    } else {
+        [self setClassName:name];
+    }
+}
+
+- (void)_removeClassName:(NSString *)name
+{
+    if ([[self className] isEqualToString:name]) {
+        [self setClassName:@""];
+    } else if ([[self className] rangeOfString:name].location != NSNotFound) {
+        NSMutableString *class = [[self className] mutableCopy];
+        [class replaceOccurrencesOfString:name withString:@"" options:NSLiteralSearch range:NSMakeRange(0, [class length])];
+        [self setClassName:[class _webkit_stringByCollapsingWhitespaceCharacters]];
+        [class release];
+    }
+}
+@end
+
+#pragma mark -
+
+@implementation DOMNode (DOMNodeInspectorAdditions)
+- (NSString *)_contentPreview
+{
+    if (![self hasChildNodes])
+        return @"";
+
+    unsigned limit = 0;
+    NSMutableString *preview = [[NSMutableString alloc] initWithCapacity:100];
+    [preview appendString:@" "];
+
+    // always skip whitespace here
+    DOMNode *currentNode = [self _traverseNextNodeSkippingWhitespaceStayingWithin:self];
+    while (currentNode) {
+        if ([currentNode nodeType] == DOM_TEXT_NODE)
+            [preview appendString:[[currentNode nodeValue] _webkit_stringByCollapsingWhitespaceCharacters]];
+        else
+            [preview appendString:[currentNode _displayName]];
+        currentNode = [currentNode _traverseNextNodeStayingWithin:self];
+        if (++limit > 4) {
+            unichar ellipsis = 0x2026;
+            [preview appendString:[NSString stringWithCharacters:&ellipsis length:1]];
+            break;
+        }
+    }
+
+    return [preview autorelease];
+}
+
+#pragma mark -
+
+- (BOOL)_isAncestorOfNode:(DOMNode *)node
+{
+    DOMNode *currentNode = [node parentNode];
+    while (currentNode) {
+        if ([self isSameNode:currentNode])
+            return YES;
+        currentNode = [currentNode parentNode];
+    }
+    return NO;
+}
+
+- (BOOL)_isDescendantOfNode:(DOMNode *)node
+{
+    return [node _isAncestorOfNode:self];
+}
+
+#pragma mark -
+
+- (BOOL)_isWhitespace
+{
+    static NSCharacterSet *characters = nil;
+    if (!characters)
+        characters = [[[NSCharacterSet whitespaceAndNewlineCharacterSet] invertedSet] retain];
+    NSRange range = [[self nodeValue] rangeOfCharacterFromSet:characters];
+    return (range.location == NSNotFound);
+}
+
+- (unsigned long)_lengthOfChildNodesIgnoringWhitespace
+{
+    if (!lengthIgnoringWhitespaceCache)
+        lengthIgnoringWhitespaceCache = NSCreateMapTable(NSObjectMapKeyCallBacks, NSIntMapValueCallBacks, 300);
+
+    void *lookup = NSMapGet(lengthIgnoringWhitespaceCache, self);
+    if (lookup)
+        return (unsigned long)lookup;
+
+    unsigned long count = 0;
+    DOMNode *node = [self _firstChildSkippingWhitespace];
+    while (node) {
+        node = [node _nextSiblingSkippingWhitespace];
+        count++;
+    }
+
+    NSMapInsert(lengthIgnoringWhitespaceCache, self, (void *)count);
+    return count;
+}
+
+- (DOMNode *)_childNodeAtIndexIgnoringWhitespace:(unsigned long)nodeIndex
+{
+    unsigned long count = 0;
+    DOMNode *node = nil;
+
+    if (!lastChildIndexIgnoringWhitespaceCache)
+        lastChildIndexIgnoringWhitespaceCache = NSCreateMapTable(NSObjectMapKeyCallBacks, NSIntMapValueCallBacks, 300);
+    if (!lastChildIgnoringWhitespaceCache)
+        lastChildIgnoringWhitespaceCache = NSCreateMapTable(NSObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 300);
+
+    void *cachedLastIndex = NSMapGet(lastChildIndexIgnoringWhitespaceCache, self);
+    if (cachedLastIndex) {
+        DOMNode *lastChild = (DOMNode *)NSMapGet(lastChildIgnoringWhitespaceCache, self);
+        if (lastChild) {
+            unsigned long cachedIndex = (unsigned long)cachedLastIndex;
+            if (nodeIndex == cachedIndex) {
+                return lastChild;
+            } else if (nodeIndex > cachedIndex) {
+                node = lastChild;
+                count = cachedIndex;
+            }
+        }
+    }
+
+    if (!node)
+        node = [self _firstChildSkippingWhitespace];
+
+    while (node && count < nodeIndex) {
+        node = [node _nextSiblingSkippingWhitespace];
+        count++;
+    }
+
+    if (node) {
+        NSMapInsert(lastChildIndexIgnoringWhitespaceCache, self, (void *)count);
+        NSMapInsert(lastChildIgnoringWhitespaceCache, self, node);
+    } else {
+        NSMapRemove(lastChildIndexIgnoringWhitespaceCache, self);
+        NSMapRemove(lastChildIgnoringWhitespaceCache, self);
+    }
+
+    return node;
+}
+
+#pragma mark -
+
+- (DOMNode *)_nextSiblingSkippingWhitespace
+{
+    DOMNode *node = [self nextSibling];
+    while ([node nodeType] == DOM_TEXT_NODE && [node _isWhitespace])
+        node = [node nextSibling];
+    return node;
+}
+
+- (DOMNode *)_previousSiblingSkippingWhitespace
+{
+    DOMNode *node = [self previousSibling];
+    while ([node nodeType] == DOM_TEXT_NODE && [node _isWhitespace])
+        node = [node previousSibling];
+    return node;
+}
+
+- (DOMNode *)_firstChildSkippingWhitespace
+{
+    DOMNode *node = [self firstChild];
+    while ([node nodeType] == DOM_TEXT_NODE && [node _isWhitespace])
+        node = [node _nextSiblingSkippingWhitespace];
+    return node;
+}
+
+- (DOMNode *)_lastChildSkippingWhitespace
+{
+    DOMNode *node = [self lastChild];
+    while ([node nodeType] == DOM_TEXT_NODE && [node _isWhitespace])
+        node = [node _previousSiblingSkippingWhitespace];
+    return node;
+}
+
+#pragma mark -
+
+- (DOMNode *)_firstAncestorCommonWithNode:(DOMNode *)node
+{
+    if ([[self parentNode] isSameNode:[node parentNode]])
+        return [self parentNode];
+
+    NSMutableArray *ancestorsOne = [[[NSMutableArray alloc] init] autorelease];
+    NSMutableArray *ancestorsTwo = [[[NSMutableArray alloc] init] autorelease];
+
+    DOMNode *currentNode = [self parentNode];
+    while (currentNode) {
+        [ancestorsOne addObject:currentNode];
+        currentNode = [currentNode parentNode];
+    }
+
+    currentNode = [node parentNode];
+    while (currentNode) {
+        [ancestorsTwo addObject:currentNode];
+        currentNode = [currentNode parentNode];
+    }
+
+    return [ancestorsOne firstObjectCommonWithArray:ancestorsTwo];
+}
+
+#pragma mark -
+
+- (DOMNode *)_traverseNextNodeStayingWithin:(DOMNode *)stayWithin
+{
+    DOMNode *node = [self firstChild];
+    if (node)
+        return node;
+
+    if ([self isSameNode:stayWithin])
+        return 0;
+
+    node = [self nextSibling];
+    if (node)
+        return node;
+
+    node = self;
+    while (node && ![node nextSibling] && (!stayWithin || ![[node parentNode] isSameNode:stayWithin]))
+        node = [node parentNode];
+
+    return [node nextSibling];
+}
+
+- (DOMNode *)_traverseNextNodeSkippingWhitespaceStayingWithin:(DOMNode *)stayWithin
+{
+    DOMNode *node = [self _firstChildSkippingWhitespace];
+    if (node)
+        return node;
+
+    if ([self isSameNode:stayWithin])
+        return 0;
+
+    node = [self _nextSiblingSkippingWhitespace];
+    if (node)
+        return node;
+
+    node = self;
+    while (node && ![node _nextSiblingSkippingWhitespace] && (!stayWithin || ![[node parentNode] isSameNode:stayWithin]))
+        node = [node parentNode];
+
+    return [node _nextSiblingSkippingWhitespace];
+}
+
+- (DOMNode *)_traversePreviousNode
+{
+    DOMNode *node = [self previousSibling];
+    while ([node lastChild])
+        node = [node lastChild];
+    if (node)
+        return node;
+    return [self parentNode];
+}
+
+- (DOMNode *)_traversePreviousNodeSkippingWhitespace
+{
+    DOMNode *node = [self _previousSiblingSkippingWhitespace];
+    while ([node _lastChildSkippingWhitespace])
+        node = [node _lastChildSkippingWhitespace];
+    if (node)
+        return node;
+    return [self parentNode];
+}
+
+#pragma mark -
+
+- (NSString *)_nodeTypeName
+{
+    switch([self nodeType]) {
+        case DOM_ELEMENT_NODE: return UI_STRING("Element", "element node type name");
+        case DOM_ATTRIBUTE_NODE: return UI_STRING("Attribute", "attribute node type name");
+        case DOM_TEXT_NODE: return UI_STRING("Text", "text node type name");
+        case DOM_CDATA_SECTION_NODE: return UI_STRING("Character Data", "character data node type name");
+        case DOM_ENTITY_REFERENCE_NODE: return UI_STRING("Entity Reference", "entity reference node type name");
+        case DOM_ENTITY_NODE: return UI_STRING("Entity", "entity node type name");
+        case DOM_PROCESSING_INSTRUCTION_NODE: return UI_STRING("Processing Instruction", "processing instruction node type name");
+        case DOM_COMMENT_NODE: return UI_STRING("Comment", "comment node type name");
+        case DOM_DOCUMENT_NODE: return UI_STRING("Document", "document node type name");
+        case DOM_DOCUMENT_TYPE_NODE: return UI_STRING("Document Type", "document type node type name");
+        case DOM_DOCUMENT_FRAGMENT_NODE: return UI_STRING("Document Fragment", "document fragment node type name");
+        case DOM_NOTATION_NODE: return UI_STRING("Notation", "notation node type name");
+    }
+    return nil;
+}
+
+- (NSString *)_shortDisplayName
+{
+    if ([self nodeType] == DOM_TEXT_NODE)
+        return UI_STRING("Text", "text node type name");
+    return [self _displayName];
+}
+
+- (NSString *)_displayName
+{
+    switch([self nodeType]) {
+        case DOM_DOCUMENT_NODE:
+            return UI_STRING("Document", "document node name");
+        case DOM_ELEMENT_NODE: {
+            if ([self hasAttributes]) {
+                NSMutableString *name = [NSMutableString stringWithFormat:@"<%@", [[self nodeName] lowercaseString]];
+                NSString *value = [(DOMElement *)self getAttribute:@"id"];
+                if ([value length])
+                    [name appendFormat:@" id=\"%@\"", value];
+                value = [(DOMElement *)self getAttribute:@"class"];
+                if ([value length])
+                    [name appendFormat:@" class=\"%@\"", value];
+                if ([[self nodeName] caseInsensitiveCompare:@"a"] == NSOrderedSame) {
+                    value = [(DOMElement *)self getAttribute:@"name"];
+                    if ([value length])
+                        [name appendFormat:@" name=\"%@\"", value];
+                    value = [(DOMElement *)self getAttribute:@"href"];
+                    if ([value length])
+                        [name appendFormat:@" href=\"%@\"", value];
+                } else if ([[self nodeName] caseInsensitiveCompare:@"img"] == NSOrderedSame) {
+                    value = [(DOMElement *)self getAttribute:@"src"];
+                    if ([value length])
+                        [name appendFormat:@" src=\"%@\"", value];
+                } else if ([[self nodeName] caseInsensitiveCompare:@"iframe"] == NSOrderedSame) {
+                    value = [(DOMElement *)self getAttribute:@"src"];
+                    if ([value length])
+                        [name appendFormat:@" src=\"%@\"", value];
+                } else if ([[self nodeName] caseInsensitiveCompare:@"input"] == NSOrderedSame) {
+                    value = [(DOMElement *)self getAttribute:@"name"];
+                    if ([value length])
+                        [name appendFormat:@" name=\"%@\"", value];
+                    value = [(DOMElement *)self getAttribute:@"type"];
+                    if ([value length])
+                        [name appendFormat:@" type=\"%@\"", value];
+                } else if ([[self nodeName] caseInsensitiveCompare:@"form"] == NSOrderedSame) {
+                    value = [(DOMElement *)self getAttribute:@"action"];
+                    if ([value length])
+                        [name appendFormat:@" action=\"%@\"", value];
+                }
+                [name appendString:@">"];
+                return name;
+            }
+            return [NSString stringWithFormat:@"<%@>", [[self nodeName] lowercaseString]];
+        }
+        case DOM_TEXT_NODE: {
+            if ([self _isWhitespace])
+                return UI_STRING("(whitespace)", "whitespace text node name");
+            NSString *value = [[self nodeValue] _webkit_stringByCollapsingWhitespaceCharacters];
+            CFStringTrimWhitespace((CFMutableStringRef)value);
+            return [NSString stringWithFormat:UI_STRING("\"%@\"", "text node name with text included"), value];
+        }
+    }
+    return [[self nodeName] lowercaseString];
+}
+@end
diff --git a/WebKit/WebInspector.subproj/WebInspectorInternal.h b/WebKit/WebInspector.subproj/WebInspectorInternal.h
new file mode 100644 (file)
index 0000000..efab836
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// This header contains WebInspector declarations that can be used anywhere in the Web Kit, but are neither SPI nor API.
+
+#import <Foundation/NSObject.h>
+#import <WebKit/WebInspector.h>
+#import <WebKit/DOMCore.h>
+
+@class WebFrame;
+@class NSView;
+@class NSPopUpButton;
+@class NSSegmentedControl;
+@class NSSearchField;
+@class NSTabView;
+@class NSTextField;
+@class NSTableView;
+@class NSOutlineView;
+@class NSTextView;
+@class NSWindow;
+@class NSNotification;
+@class WebNodeHighlight;
+@class DOMCSSRuleList;
+
+@interface WebInspectorPrivate : NSObject
+{
+@public
+    WebView *webView;
+    DOMHTMLDocument *domDocument;
+    WebFrame *webFrame;
+    DOMNode *rootNode;
+    DOMNode *focusedNode;
+    NSString *searchQuery;
+    NSMutableSet *nodeCache;
+    NSMutableArray *searchResults;
+    NSScrollView *treeScrollView;
+    NSOutlineView *treeOutlineView;
+    DOMCSSRuleList *matchedRules;
+    WebNodeHighlight *currentHighlight;
+    NSImage *rightArrowImage;
+    NSImage *downArrowImage;
+    BOOL ignoreWhitespace;
+    BOOL windowLoaded;
+    BOOL webViewLoaded;
+    BOOL searchResultsVisible;
+    BOOL preventHighlight;
+    BOOL preventRevealOnFocus;
+    BOOL preventSelectionRefocus;
+    BOOL isSharedInspector;
+}
+@end
+
+@interface WebInspector (WebInspectorPrivate) <DOMEventListener>
+- (void)_highlightNode:(DOMNode *)node;
+- (void)_revealAndSelectNodeInTree:(DOMNode *)node;
+- (void)_update;
+- (void)_updateRoot;
+- (void)_updateTreeScrollbar;
+- (void)_showSearchResults:(BOOL)show;
+- (void)_refreshSearch;
+@end
+
+@interface DOMHTMLElement (DOMHTMLElementInspectorAdditions)
+- (void)_addClassName:(NSString *)name;
+- (void)_removeClassName:(NSString *)name;
+@end
+
+@interface DOMNode (DOMNodeInspectorAdditions)
+- (NSString *)_contentPreview;
+
+- (BOOL)_isAncestorOfNode:(DOMNode *)node;
+- (BOOL)_isDescendantOfNode:(DOMNode *)node;
+
+- (BOOL)_isWhitespace;
+
+- (unsigned long)_lengthOfChildNodesIgnoringWhitespace;
+- (DOMNode *)_childNodeAtIndexIgnoringWhitespace:(unsigned long)nodeIndex;
+
+- (DOMNode *)_nextSiblingSkippingWhitespace;
+- (DOMNode *)_previousSiblingSkippingWhitespace;
+
+- (DOMNode *)_firstChildSkippingWhitespace;
+- (DOMNode *)_lastChildSkippingWhitespace;
+
+- (DOMNode *)_firstAncestorCommonWithNode:(DOMNode *)node;
+
+- (DOMNode *)_traverseNextNodeStayingWithin:(DOMNode *)stayWithin;
+- (DOMNode *)_traverseNextNodeSkippingWhitespaceStayingWithin:(DOMNode *)stayWithin;
+- (DOMNode *)_traversePreviousNode;
+- (DOMNode *)_traversePreviousNodeSkippingWhitespace;
+
+- (NSString *)_nodeTypeName;
+- (NSString *)_shortDisplayName;
+- (NSString *)_displayName;
+@end
+
+@interface NSWindow (NSWindowContentShadow)
+- (void)_setContentHasShadow:(BOOL)hasShadow;
+@end
diff --git a/WebKit/WebInspector.subproj/WebInspectorOutlineView.h b/WebKit/WebInspector.subproj/WebInspectorOutlineView.h
new file mode 100644 (file)
index 0000000..8c8ab66
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <AppKit/NSOutlineView.h>
+
+@interface WebInspectorOutlineView : NSOutlineView
+@end
diff --git a/WebKit/WebInspector.subproj/WebInspectorOutlineView.m b/WebKit/WebInspector.subproj/WebInspectorOutlineView.m
new file mode 100644 (file)
index 0000000..a9d8745
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "WebInspectorOutlineView.h"
+
+@implementation WebInspectorOutlineView
+- (BOOL)isOpaque
+{
+    return NO;
+}
+
+- (NSColor *)_highlightColorForCell:(NSCell *)cell
+{
+    // return nil to prevent normal selection drawing
+    return nil;
+}
+
+- (void)_highlightRow:(int)row clipRect:(NSRect)clip {
+    NSColor *selectionColor = nil;
+    if ([[self window] firstResponder] == self && [[self window] isKeyWindow])
+        selectionColor = [[NSColor alternateSelectedControlColor] colorWithAlphaComponent:0.333];
+    selectionColor = [[NSColor alternateSelectedControlColor] colorWithAlphaComponent:0.45];
+
+    if ([self numberOfColumns] > 0) {
+        NSRect highlight = [self rectOfRow:row];
+        NSRect drawRect = NSIntersectionRect(clip, highlight);
+        BOOL solid = ([[self window] firstResponder] == self && [[self window] isKeyWindow]);
+        if (NSContainsRect(drawRect,clip) && !NSEqualRects(drawRect,highlight)) {
+            // draw a solid rect when the outline view wants to draw inside the row rect
+            if ([NSGraphicsContext currentContextDrawingToScreen] && solid) {
+                [selectionColor set];
+                NSRectFillUsingOperation(drawRect, NSCompositeSourceOver);
+            }
+        } else {
+            // draw a rounded rect for the full row
+            if ([NSGraphicsContext currentContextDrawingToScreen]) {
+                NSBezierPath *path = [[NSBezierPath alloc] init];
+
+                float radius = 6.0;
+                NSRect irect = NSInsetRect(highlight, radius, radius);
+                if (!solid)
+                    irect = NSInsetRect(irect, 1.0, 1.0);
+                [path appendBezierPathWithArcWithCenter:NSMakePoint(NSMinX(irect), NSMinY(irect)) radius:radius startAngle:180. endAngle:270.];
+                [path appendBezierPathWithArcWithCenter:NSMakePoint(NSMaxX(irect), NSMinY(irect)) radius:radius startAngle:270. endAngle:360.];
+                [path appendBezierPathWithArcWithCenter:NSMakePoint(NSMaxX(irect), NSMaxY(irect)) radius:radius startAngle:0. endAngle:90.];
+                [path appendBezierPathWithArcWithCenter:NSMakePoint(NSMinX(irect), NSMaxY(irect)) radius:radius startAngle:90. endAngle:180.];
+                [path closePath];
+
+                NSRectClip(clip);
+                [selectionColor set];
+                if (solid) {
+                    [path fill];
+                } else {
+                    [path setLineWidth:2.0];
+                    [path stroke];
+                }
+
+                [path release];
+            }
+        }
+    }
+}
+
+- (void)drawBackgroundInClipRect:(NSRect)clipRect
+{
+    // don't draw a background
+}
+@end
diff --git a/WebKit/WebInspector.subproj/WebInspectorPanel.h b/WebKit/WebInspector.subproj/WebInspectorPanel.h
new file mode 100644 (file)
index 0000000..be1b87c
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <AppKit/NSPanel.h>
+
+@interface WebInspectorPanel : NSPanel {
+    BOOL _mouseInRegion;
+}
+@end
diff --git a/WebKit/WebInspector.subproj/WebInspectorPanel.m b/WebKit/WebInspector.subproj/WebInspectorPanel.m
new file mode 100644 (file)
index 0000000..047fb2c
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "WebInspectorPanel.h"
+
+#import <WebKit/WebView.h>
+#import <WebKit/WebViewPrivate.h>
+#import <WebKit/WebDashboardRegion.h>
+#import <WebKit/DOMCore.h>
+#import <WebKit/DOMHTML.h>
+#import <WebKit/DOMCSS.h>
+
+@implementation WebInspectorPanel
+- (BOOL)canBecomeKeyWindow
+{
+    return YES;
+}
+
+- (BOOL)canBecomeMainWindow
+{
+    return YES;
+}
+
+- (void)moveWindow:(NSEvent *)event
+{
+    NSPoint startLocation = [event locationInWindow];
+    NSPoint lastLocation = startLocation;
+    BOOL mouseUpOccurred = NO;
+
+    while (!mouseUpOccurred) {
+        // set mouseUp flag here, but process location of event before exiting from loop, leave mouseUp in queue
+        event = [self nextEventMatchingMask:(NSLeftMouseDraggedMask | NSLeftMouseUpMask) untilDate:[NSDate distantFuture] inMode:NSEventTrackingRunLoopMode dequeue:YES];
+
+        if ([event type] == NSLeftMouseUp)
+            mouseUpOccurred = YES;
+
+        NSPoint newLocation = [event locationInWindow];
+        if (NSEqualPoints(newLocation, lastLocation))
+            continue;
+
+        NSPoint origin = [self frame].origin;
+        [self setFrameOrigin:NSMakePoint(origin.x + newLocation.x - startLocation.x, origin.y + newLocation.y - startLocation.y)];
+        lastLocation = newLocation;
+    }
+}
+
+- (void)resizeWindow:(NSEvent *)event
+{
+    NSRect startFrame = [self frame];
+    NSPoint startLocation = [self convertBaseToScreen:[event locationInWindow]];
+    NSPoint lastLocation = startLocation;
+    NSSize minSize = [self minSize];
+    NSSize maxSize = [self maxSize];
+    BOOL mouseUpOccurred = NO;
+
+    while (!mouseUpOccurred) {
+        // set mouseUp flag here, but process location of event before exiting from loop, leave mouseUp in queue
+        event = [self nextEventMatchingMask:(NSLeftMouseDraggedMask | NSLeftMouseUpMask) untilDate:[NSDate distantFuture] inMode:NSEventTrackingRunLoopMode dequeue:YES];
+
+        if ([event type] == NSLeftMouseUp)
+            mouseUpOccurred = YES;
+
+        NSPoint newLocation = [self convertBaseToScreen:[event locationInWindow]];
+        if (NSEqualPoints(newLocation, lastLocation))
+            continue;
+
+        NSRect proposedRect = startFrame;
+        proposedRect.size.width += newLocation.x - startLocation.x;;
+        proposedRect.size.height -= newLocation.y - startLocation.y;
+        proposedRect.origin.y += newLocation.y - startLocation.y;
+
+        if (proposedRect.size.width < minSize.width) {
+            proposedRect.size.width = minSize.width;
+        } else if (proposedRect.size.width > maxSize.width) {
+            proposedRect.size.width = maxSize.width;
+        }
+
+        if (proposedRect.size.height < minSize.height) {
+            proposedRect.origin.y -= minSize.height - proposedRect.size.height;
+            proposedRect.size.height = minSize.height;
+        } else if (proposedRect.size.height > maxSize.height) {
+            proposedRect.origin.y -= maxSize.height - proposedRect.size.height;
+            proposedRect.size.height = maxSize.height;
+        }
+
+        [self setFrame:proposedRect display:YES];
+        lastLocation = newLocation;
+    }
+}
+
+- (void)sendEvent:(NSEvent *)event
+{
+    if (_mouseInRegion && [event type] == NSLeftMouseUp)
+        _mouseInRegion = NO;
+
+    if (([event type] == NSLeftMouseDown || [event type] == NSLeftMouseDragged) && !_mouseInRegion) {
+        NSPoint pointInView = [[[[(WebView *)[self contentView] mainFrame] frameView] documentView] convertPoint:[event locationInWindow] fromView:nil];
+        NSDictionary *regions = [(WebView *)[self contentView] _dashboardRegions];
+
+        WebDashboardRegion *region = [[regions objectForKey:@"resizeTop"] lastObject];
+        region = [[regions objectForKey:@"resize"] lastObject];
+        if (region) {
+            if (NSPointInRect(pointInView, [region dashboardRegionClip])) {
+                // we are in a resize control region, resize the window now and eat the event
+                [self resizeWindow:event];
+                return;
+            }
+        }
+
+        NSArray *controlRegions = [regions objectForKey:@"control"];
+        NSEnumerator *enumerator = [controlRegions objectEnumerator];
+        while ((region = [enumerator nextObject])) {
+            if (NSPointInRect(pointInView, [region dashboardRegionClip])) {
+                // we are in a control region, lets pass the event down
+                _mouseInRegion = YES;
+                [super sendEvent:event];
+                return;
+            }
+        }
+
+        // if we are dragging and the mouse isn't in a control region move the window
+        if ([event type] == NSLeftMouseDragged) {
+            [self moveWindow:event];
+            return;
+        }
+    }
+
+    [super sendEvent:event];
+}
+@end
diff --git a/WebKit/WebInspector.subproj/WebNodeHighlight.h b/WebKit/WebInspector.subproj/WebNodeHighlight.h
new file mode 100644 (file)
index 0000000..a922d87
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+@class WebNodeHighlightView;
+
+@interface WebNodeHighlight : NSObject
+{
+    NSWindow *_webNodeHighlightWindow;
+    WebNodeHighlightView *_webNodeHighlightView;
+    NSTimer *_timer;
+    CFAbsoluteTime _startTime;
+    CFTimeInterval _duration;
+}
+- (id)initWithBounds:(NSRect)bounds andRects:(NSArray *)rects forView:(NSView *)view;
+- (double)fractionComplete;
+- (void)expire;
+@end
diff --git a/WebKit/WebInspector.subproj/WebNodeHighlight.m b/WebKit/WebInspector.subproj/WebNodeHighlight.m
new file mode 100644 (file)
index 0000000..37bec53
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <mach/mach_time.h>
+#import "WebNodeHighlightView.h"
+#import "WebNodeHighlight.h"
+
+@implementation WebNodeHighlight
+- (id)initWithBounds:(NSRect)bounds andRects:(NSArray *)rects forView:(NSView *)view
+{
+    if (![self init])
+        return nil;
+
+    _startTime = 0.0;
+    _duration = 3.0;
+
+    if ([[[NSApplication sharedApplication] currentEvent] modifierFlags] & NSShiftKeyMask)
+        _duration = 6.0;
+
+    if (!rects)
+        rects = [NSArray arrayWithObject:[NSValue valueWithRect:bounds]];
+
+    _webNodeHighlightView = [[WebNodeHighlightView alloc] initWithHighlight:self andRects:rects forView:view];
+    if (!_webNodeHighlightView) {
+        [self release];
+        return nil;
+    }
+
+    // adjust size and position for rect padding that the view adds
+    bounds.origin.y -= 3.0;
+    bounds.origin.x -= 3.0;
+    bounds.size = [_webNodeHighlightView frame].size;
+
+    NSRect windowBounds = [view convertRect:bounds toView:nil];
+    windowBounds.origin = [[view window] convertBaseToScreen:windowBounds.origin]; // adjust for screen coords
+
+    _webNodeHighlightWindow = [[NSWindow alloc] initWithContentRect:windowBounds styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES];
+    [_webNodeHighlightWindow setBackgroundColor:[NSColor clearColor]];
+    [_webNodeHighlightWindow setOpaque:NO];
+    [_webNodeHighlightWindow setHasShadow:NO];
+    [_webNodeHighlightWindow setIgnoresMouseEvents:YES];
+    [_webNodeHighlightWindow setReleasedWhenClosed:YES];
+    [_webNodeHighlightWindow setLevel:[[view window] level] + 1];
+    [_webNodeHighlightWindow setContentView:_webNodeHighlightView];
+    [_webNodeHighlightView release];
+
+    [_webNodeHighlightWindow orderFront:self];
+
+    // 30 frames per second time interval will play well with the CPU and still look smooth
+    _timer = [[NSTimer scheduledTimerWithTimeInterval:(1.0 / 30.0) target:self selector:@selector(redraw:) userInfo:nil repeats:YES] retain];
+
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(expire) name:NSViewBoundsDidChangeNotification object:view];
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(expire) name:NSViewBoundsDidChangeNotification object:[view superview]];
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(expire) name:NSWindowWillMoveNotification object:[view window]];
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(expire) name:NSWindowWillCloseNotification object:[view window]];
+
+    return self;
+}
+
+- (void)dealloc
+{
+    [[NSNotificationCenter defaultCenter] removeObserver:self name:NSViewBoundsDidChangeNotification object:nil];
+    [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillMoveNotification object:nil];
+    [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowWillCloseNotification object:nil];
+
+    [_timer invalidate];
+    [_timer release];
+
+    [super dealloc];
+}
+
+- (double)fractionComplete
+{
+    if (_startTime == 0.0)
+        _startTime = CFAbsoluteTimeGetCurrent();
+
+    return ((CFAbsoluteTimeGetCurrent() - _startTime) / _duration);
+}
+
+- (void)expire
+{
+    [_timer invalidate];
+    [_timer release];
+    _timer = nil;
+
+    [_webNodeHighlightWindow close];
+    _webNodeHighlightWindow = nil;
+
+    [[NSNotificationCenter defaultCenter] postNotificationName:@"WebNodeHighlightExpired" object:self userInfo:nil];
+}
+
+- (void)redraw:(NSTimer *)timer
+{
+    [_webNodeHighlightView setNeedsDisplay:YES];    
+
+    if (_startTime == 0.0)
+        _startTime = CFAbsoluteTimeGetCurrent();
+
+    if ((CFAbsoluteTimeGetCurrent() - _startTime) > _duration)
+        [self expire];
+}
+@end
diff --git a/WebKit/WebInspector.subproj/WebNodeHighlightView.h b/WebKit/WebInspector.subproj/WebNodeHighlightView.h
new file mode 100644 (file)
index 0000000..bc31453
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+@class WebNodeHighlight;
+
+@interface WebNodeHighlightView : NSView
+{
+    WebNodeHighlight *_highlight;
+    NSImage *_highlightRingImage;
+}
+- (id)initWithHighlight:(WebNodeHighlight *)hightlight andRects:(NSArray *)rects forView:(NSView *)view;
+@end
diff --git a/WebKit/WebInspector.subproj/WebNodeHighlightView.m b/WebKit/WebInspector.subproj/WebNodeHighlightView.m
new file mode 100644 (file)
index 0000000..9affec1
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "WebNodeHighlight.h"
+#import "WebNodeHighlightView.h"
+#import <WebKitSystemInterface.h>
+
+@implementation WebNodeHighlightView
+- (NSBezierPath *)roundedRect:(NSRect)rect withRadius:(float)radius
+{
+    NSBezierPath *path = [[NSBezierPath alloc] init];
+
+    NSRect irect = NSInsetRect( rect, radius, radius );
+    [path appendBezierPathWithArcWithCenter:NSMakePoint(NSMinX(irect), NSMinY(irect)) radius:radius startAngle:180. endAngle:270.];
+    [path appendBezierPathWithArcWithCenter:NSMakePoint(NSMaxX(irect), NSMinY(irect)) radius:radius startAngle:270. endAngle:360.];
+    [path appendBezierPathWithArcWithCenter:NSMakePoint(NSMaxX(irect), NSMaxY(irect)) radius:radius startAngle:0. endAngle:90.];
+    [path appendBezierPathWithArcWithCenter:NSMakePoint(NSMinX(irect), NSMaxY(irect)) radius:radius startAngle:90. endAngle:180.];
+    [path closePath];
+
+    return [path autorelease];
+}
+
+- (id)initWithHighlight:(WebNodeHighlight *)highlight andRects:(NSArray *)rects forView:(NSView *)view
+{
+    if (![self init])
+        return nil;
+
+    _highlight = highlight; // don't retain, would cause a circular retain
+
+    NSRect visibleRect = [view visibleRect];
+
+    NSRect rect = NSZeroRect;
+    NSBezierPath *path = nil;
+    NSBezierPath *straightPath = nil;
+
+    if([rects count] == 1) {
+        NSValue *value = (NSValue *)[rects objectAtIndex:0];
+        rect = NSInsetRect([value rectValue], -1.0, -1.0);
+        rect = NSIntersectionRect(rect, visibleRect);
+        if (!NSIsEmptyRect(rect))
+            path = [[self roundedRect:rect withRadius:3.0] retain];
+
+        // shift everything to the corner
+        NSAffineTransform *transform = [[NSAffineTransform alloc] init];
+        [transform translateXBy:(NSMinX(rect) * -1.0) + 2.5 yBy:(NSMinY(rect) * -1.0) + 2.5];
+        [path transformUsingAffineTransform:transform];
+        [straightPath transformUsingAffineTransform:transform];
+        [transform release];
+    } else if ([rects count] > 1) {
+        path = [[NSBezierPath alloc] init];
+        straightPath = [path copy];
+
+        // roundedRect: returns an autoreleased path, so release them soon with a pool
+        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+        NSEnumerator *enumerator = [rects objectEnumerator];
+        NSValue *value = nil;
+        while ((value = [enumerator nextObject])) {
+            rect = NSIntersectionRect([value rectValue], visibleRect);
+            if (!NSIsEmptyRect(rect)) {
+                [straightPath appendBezierPathWithRect:rect];
+                [path appendBezierPath:[self roundedRect:rect withRadius:3.0]];
+            }
+        }
+
+        [pool drain];
+        [pool release];
+
+        rect = [path bounds];
+
+        [straightPath setWindingRule:NSNonZeroWindingRule];
+        [straightPath setLineJoinStyle:NSRoundLineJoinStyle];
+        [straightPath setLineCapStyle:NSRoundLineCapStyle];
+
+        // multiple rects we get from WebCore need flipped to show up correctly
+        NSAffineTransform *transform = [[NSAffineTransform alloc] init];
+        [transform scaleXBy:1.0 yBy:-1.0];
+        [path transformUsingAffineTransform:transform];
+        [straightPath transformUsingAffineTransform:transform];
+        [transform release];
+
+        // shift everything to the corner
+        transform = [[NSAffineTransform alloc] init];
+        [transform translateXBy:(NSMinX(rect) * -1.0) + 2.5 yBy:NSMaxY(rect) + 2.5];
+        [path transformUsingAffineTransform:transform];
+        [straightPath transformUsingAffineTransform:transform];
+        [transform release];
+    }
+
+    if (!path || [path isEmpty]) {
+        [self release];
+        return nil;
+    }
+
+    [path setWindingRule:NSNonZeroWindingRule];
+    [path setLineJoinStyle:NSRoundLineJoinStyle];
+    [path setLineCapStyle:NSRoundLineCapStyle];
+
+    // make the drawing area larger for the focus ring blur
+    rect = [path bounds];
+    rect.size.width += 5.0;
+    rect.size.height += 5.0;
+    [self setFrameSize:rect.size];
+
+    // draw into an image
+    _highlightRingImage = [[NSImage alloc] initWithSize:rect.size];
+    [_highlightRingImage lockFocus];
+    [NSGraphicsContext saveGraphicsState];
+
+    if (straightPath) {
+        [[NSColor redColor] set];
+        [path setLineWidth:4.0];
+        [path stroke];
+
+        // clear the center to eliminate thick inner strokes for overlapping rects
+        [[NSGraphicsContext currentContext] setCompositingOperation:NSCompositeClear];
+        [path fill];
+
+        // stroke the straight line path with a light color to show any inner rects
+        [[NSGraphicsContext currentContext] setCompositingOperation:NSCompositeDestinationOver];
+        [[[NSColor redColor] colorWithAlphaComponent:0.6] set];
+        [straightPath setLineWidth:1.0];
+        [straightPath stroke];
+    } else {
+        [[NSColor redColor] set];
+        [path setLineWidth:2.0];
+        [path stroke];
+    }
+
+    [NSGraphicsContext restoreGraphicsState];
+    [_highlightRingImage unlockFocus];
+
+    [path release];
+    [straightPath release];
+
+    return self;
+}
+
+- (void)dealloc
+{
+    [_highlightRingImage release];
+    [super dealloc];
+}
+
+- (BOOL)isOpaque
+{
+    return NO;
+}
+
+- (void)drawRect:(NSRect)rect
+{
+    double alpha = 1.0 - [_highlight fractionComplete];
+    if (alpha > 1.0)
+        alpha = 1.0;
+    else if (alpha < 0.0)
+        alpha = 0.0;
+
+    [_highlightRingImage drawInRect:rect fromRect:rect operation:NSCompositeCopy fraction:alpha];
+}
+@end
diff --git a/WebKit/WebInspector.subproj/webInspector/Images/close.png b/WebKit/WebInspector.subproj/webInspector/Images/close.png
new file mode 100644 (file)
index 0000000..037d8e9
Binary files /dev/null and b/WebKit/WebInspector.subproj/webInspector/Images/close.png differ
diff --git a/WebKit/WebInspector.subproj/webInspector/Images/closePressed.png b/WebKit/WebInspector.subproj/webInspector/Images/closePressed.png
new file mode 100644 (file)
index 0000000..f192a82
Binary files /dev/null and b/WebKit/WebInspector.subproj/webInspector/Images/closePressed.png differ
diff --git a/WebKit/WebInspector.subproj/webInspector/Images/downTriangle.png b/WebKit/WebInspector.subproj/webInspector/Images/downTriangle.png
new file mode 100644 (file)
index 0000000..cc920fd
Binary files /dev/null and b/WebKit/WebInspector.subproj/webInspector/Images/downTriangle.png differ
diff --git a/WebKit/WebInspector.subproj/webInspector/Images/menu.png b/WebKit/WebInspector.subproj/webInspector/Images/menu.png
new file mode 100644 (file)
index 0000000..fca9fde
Binary files /dev/null and b/WebKit/WebInspector.subproj/webInspector/Images/menu.png differ
diff --git a/WebKit/WebInspector.subproj/webInspector/Images/menuPressed.png b/WebKit/WebInspector.subproj/webInspector/Images/menuPressed.png
new file mode 100644 (file)
index 0000000..55d15a0
Binary files /dev/null and b/WebKit/WebInspector.subproj/webInspector/Images/menuPressed.png differ
diff --git a/WebKit/WebInspector.subproj/webInspector/Images/popupFill.png b/WebKit/WebInspector.subproj/webInspector/Images/popupFill.png
new file mode 100644 (file)
index 0000000..782af38
Binary files /dev/null and b/WebKit/WebInspector.subproj/webInspector/Images/popupFill.png differ
diff --git a/WebKit/WebInspector.subproj/webInspector/Images/popupFillPressed.png b/WebKit/WebInspector.subproj/webInspector/Images/popupFillPressed.png
new file mode 100644 (file)
index 0000000..f0c67cf
Binary files /dev/null and b/WebKit/WebInspector.subproj/webInspector/Images/popupFillPressed.png differ
diff --git a/WebKit/WebInspector.subproj/webInspector/Images/popupLeft.png b/WebKit/WebInspector.subproj/webInspector/Images/popupLeft.png
new file mode 100644 (file)
index 0000000..4d1aaa3
Binary files /dev/null and b/WebKit/WebInspector.subproj/webInspector/Images/popupLeft.png differ
diff --git a/WebKit/WebInspector.subproj/webInspector/Images/popupLeftPressed.png b/WebKit/WebInspector.subproj/webInspector/Images/popupLeftPressed.png
new file mode 100644 (file)
index 0000000..f9ffbf2
Binary files /dev/null and b/WebKit/WebInspector.subproj/webInspector/Images/popupLeftPressed.png differ
diff --git a/WebKit/WebInspector.subproj/webInspector/Images/popupRight.png b/WebKit/WebInspector.subproj/webInspector/Images/popupRight.png
new file mode 100644 (file)
index 0000000..e04e1ba
Binary files /dev/null and b/WebKit/WebInspector.subproj/webInspector/Images/popupRight.png differ
diff --git a/WebKit/WebInspector.subproj/webInspector/Images/popupRightPressed.png b/WebKit/WebInspector.subproj/webInspector/Images/popupRightPressed.png
new file mode 100644 (file)
index 0000000..8301a47
Binary files /dev/null and b/WebKit/WebInspector.subproj/webInspector/Images/popupRightPressed.png differ
diff --git a/WebKit/WebInspector.subproj/webInspector/Images/rightTriangle.png b/WebKit/WebInspector.subproj/webInspector/Images/rightTriangle.png
new file mode 100644 (file)
index 0000000..33b500a
Binary files /dev/null and b/WebKit/WebInspector.subproj/webInspector/Images/rightTriangle.png differ
diff --git a/WebKit/WebInspector.subproj/webInspector/Images/scrollThumbBottom.png b/WebKit/WebInspector.subproj/webInspector/Images/scrollThumbBottom.png
new file mode 100644 (file)
index 0000000..b0b3883
Binary files /dev/null and b/WebKit/WebInspector.subproj/webInspector/Images/scrollThumbBottom.png differ
diff --git a/WebKit/WebInspector.subproj/webInspector/Images/scrollThumbMiddle.png b/WebKit/WebInspector.subproj/webInspector/Images/scrollThumbMiddle.png
new file mode 100644 (file)
index 0000000..ccdce6f
Binary files /dev/null and b/WebKit/WebInspector.subproj/webInspector/Images/scrollThumbMiddle.png differ
diff --git a/WebKit/WebInspector.subproj/webInspector/Images/scrollThumbTop.png b/WebKit/WebInspector.subproj/webInspector/Images/scrollThumbTop.png
new file mode 100644 (file)
index 0000000..543360a
Binary files /dev/null and b/WebKit/WebInspector.subproj/webInspector/Images/scrollThumbTop.png differ
diff --git a/WebKit/WebInspector.subproj/webInspector/Images/scrollTrackBottom.png b/WebKit/WebInspector.subproj/webInspector/Images/scrollTrackBottom.png
new file mode 100644 (file)
index 0000000..226c33b
Binary files /dev/null and b/WebKit/WebInspector.subproj/webInspector/Images/scrollTrackBottom.png differ
diff --git a/WebKit/WebInspector.subproj/webInspector/Images/scrollTrackMiddle.png b/WebKit/WebInspector.subproj/webInspector/Images/scrollTrackMiddle.png
new file mode 100644 (file)
index 0000000..a9f76ea
Binary files /dev/null and b/WebKit/WebInspector.subproj/webInspector/Images/scrollTrackMiddle.png differ
diff --git a/WebKit/WebInspector.subproj/webInspector/Images/scrollTrackTop.png b/WebKit/WebInspector.subproj/webInspector/Images/scrollTrackTop.png
new file mode 100644 (file)
index 0000000..c295186
Binary files /dev/null and b/WebKit/WebInspector.subproj/webInspector/Images/scrollTrackTop.png differ
diff --git a/WebKit/WebInspector.subproj/webInspector/Images/squareButtonRight.png b/WebKit/WebInspector.subproj/webInspector/Images/squareButtonRight.png
new file mode 100644 (file)
index 0000000..504104f
Binary files /dev/null and b/WebKit/WebInspector.subproj/webInspector/Images/squareButtonRight.png differ
diff --git a/WebKit/WebInspector.subproj/webInspector/Images/squareButtonRightPressed.png b/WebKit/WebInspector.subproj/webInspector/Images/squareButtonRightPressed.png
new file mode 100644 (file)
index 0000000..70a6769
Binary files /dev/null and b/WebKit/WebInspector.subproj/webInspector/Images/squareButtonRightPressed.png differ
diff --git a/WebKit/WebInspector.subproj/webInspector/Images/upTriangle.png b/WebKit/WebInspector.subproj/webInspector/Images/upTriangle.png
new file mode 100644 (file)
index 0000000..f731cb2
Binary files /dev/null and b/WebKit/WebInspector.subproj/webInspector/Images/upTriangle.png differ
diff --git a/WebKit/WebInspector.subproj/webInspector/inspector.css b/WebKit/WebInspector.subproj/webInspector/inspector.css
new file mode 100644 (file)
index 0000000..e35da5e
--- /dev/null
@@ -0,0 +1,757 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+html {
+    height: 100%;
+}
+
+body {
+    overflow: hidden;
+    height: 100%;
+}
+
+* {
+    -apple-user-select: none;
+}
+
+a {
+    cursor: default;
+}
+
+button {
+    -apple-dashboard-region: dashboard-region(control rectangle);
+}
+
+.disabled {
+    color: rgba(255,255,255,0.5);
+}
+
+#body {
+    position: absolute;
+    background-color: rgba(20,20,20,0.9);
+    border-radius: 8px;
+    top: 0;
+    height: 100%;
+    left: 0;
+    right: 0;
+    color: white;
+    font-family: Lucida Grande, sans-serif;
+    font-size: 12px;
+    text-shadow: black 0px 1px 2px;
+}
+
+#title {
+    position: absolute;
+    background-color: rgba(255,255,255,0.1);
+    border-top-left-radius: 8px;
+    border-top-right-radius: 8px;
+    height: 20px;
+    top: 0;
+    left: 0;
+    right: 0;
+    text-align: center;
+    font-size: 11px;
+    line-height: 20px;
+}
+
+#header {
+    position: absolute;
+    height: 26px;
+    top: 0;
+    left: 0;
+    right: 0;
+}
+
+#search {
+    font-size: 11px;
+    position: absolute;
+    top: 1px;
+    right: 10px;
+    width: 90px;
+}
+
+#searchCount {
+    font-size: 11px;
+    position: absolute;
+    top: 2px;
+    right: 110px;
+    width: 100px;
+    text-align: right;
+    display: none;
+}
+
+#treePopup {
+    position: absolute;
+    top: 4px;
+    left: 54px;
+    right: 106px;
+}
+
+#treePopupButton {
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+}
+
+#realTreePopup {
+    opacity: 0;
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    z-index: 10;
+    margin: 0;
+    padding: 0;
+}
+
+#treePopupTitleArea {
+    overflow: hidden;
+    white-space: nowrap;
+}
+
+#traverse {
+    position: absolute;
+    top: 4px;
+    left: 8px;
+    width: 50px;
+}
+
+#traverseUp .middle {
+    right: 0;
+}
+
+#traverseUp .middle > img {
+    position: absolute;
+    top: 4px;
+    left: 1px;
+}
+
+#traverseDown .middle {
+    left: 1px;
+}
+
+#traverseDown .middle > img {
+    position: absolute;
+    top: 5px;
+    left: 5px;
+}
+
+#traverseUp {
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 20px;
+}
+
+#traverseDown {
+    position: absolute;
+    top: 0;
+    left: 20px;
+    width: 21px;
+}
+
+#traverseDown > img {
+    position: absolute;
+    top: 0;
+    left: 0;
+}
+
+#tabs {
+    position: absolute;
+    top: 3px;
+    left: 50%;
+    margin-left: -130px;
+}
+
+#tabs .middle {
+    left: 0;
+    right: 0;
+    text-align: center;
+}
+
+#tabs button > img {
+    position: absolute;
+    top: 0;
+    left: 0;
+}
+
+#nodeButton {
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 60px;
+}
+
+#nodeButton .middle {
+    padding-right: 6px;
+    left: 6px;
+    right: 0;
+}
+
+#metricsButton {
+    position: absolute;
+    top: 0;
+    left: 115px;
+    width: 65px;
+}
+
+#styleButton {
+    position: absolute;
+    top: 0;
+    left: 60px;
+    width: 55px;
+}
+
+#javascriptButton {
+    position: absolute;
+    top: 0;
+    left: 180px;
+    width: 80px;
+}
+
+#javascriptButton .middle {
+    padding-left: 6px;
+    left: 0;
+    right: 6px;
+}
+
+#title button.close {
+    position: absolute;
+    top: 4px;
+    left: 5px;
+    border: 0;
+    background-color: transparent;
+    background-image: url( Images/close.png );
+    background-repeat: no-repeat;
+    height: 13px;
+    width: 13px;
+}
+
+#title button.close[disabled] {
+    opacity: 0.5;
+}
+
+#title button.close:active {
+    background-image: url( Images/closePressed.png );
+}
+
+#title button.menu {
+    position: absolute;
+    top: 4px;
+    right: 5px;
+    border: 0;
+    background-color: transparent;
+    background-image: url( Images/menu.png );
+    background-repeat: no-repeat;
+    height: 13px;
+    width: 13px;
+}
+
+#title button.menu[disabled] {
+    opacity: 0.5;
+}
+
+#title button.menu:active {
+    background-image: url( Images/menuPressed.png );
+}
+
+button.popup {
+    height: 20px;
+    border: 0;
+    background-color: transparent;
+    color: white;
+    padding: 0;
+    margin: 0;
+}
+
+button.popup .left {
+    position: absolute;
+    top: 0;
+    left: 0;
+    height: 20px;
+    width: 6px;
+    background-image: url( Images/popupLeft.png );
+    background-repeat: no-repeat;
+}
+
+button.popup .middle {
+    position: absolute;
+    top: 0;
+    left: 6px;
+    right: 19px;
+    height: 20px;
+    line-height: 1em;
+    background-image: url( Images/popupFill.png );
+    background-repeat: repeat-x;
+    line-height: 17px;
+    text-align: left;
+    padding: 0 2px;
+    overflow: hidden;
+    text-overflow: ellipsis;
+}
+
+button.popup .right {
+    position: absolute;
+    top: 0;
+    right: 0;
+    height: 20px;
+    width: 19px;
+    background-image: url( Images/popupRight.png );
+    background-repeat: no-repeat;
+}
+
+button.popup[disabled] {
+    opacity: 0.5;
+}
+
+button.popup[disabled] .left {
+    background-image: url( Images/popupLeft.png ) !important;
+}
+
+button.popup[disabled] .middle {
+    background-image: url( Images/popupFill.png ) !important;
+}
+
+button.popup[disabled] .right {
+    background-image: url( Images/popupRight.png ) !important;
+}
+
+button.popup:active .left {
+    background-image: url( Images/popupLeftPressed.png );
+}
+
+button.popup:active .middle {
+    background-image: url( Images/popupFillPressed.png );
+    text-shadow: black 1px -1px 3px;
+}
+
+button.popup:active .right {
+    background-image: url( Images/popupRightPressed.png );
+}
+
+button.square {
+    height: 20px;
+    border: 0;
+    background-color: transparent;
+    color: white;
+    padding: 0;
+    margin: 0;
+}
+
+button.square .left {
+    position: absolute;
+    top: 0;
+    left: 0;
+    height: 20px;
+    width: 6px;
+    background-image: url( Images/popupLeft.png );
+    background-repeat: no-repeat;
+}
+
+button.square .middle {
+    position: absolute;
+    top: 0;
+    left: 6px;
+    right: 6px;
+    height: 20px;
+    line-height: 1em;
+    background-image: url( Images/popupFill.png );
+    background-repeat: repeat-x;
+    line-height: 17px;
+    text-align: left;
+    padding: 0 2px;
+}
+
+button.square .right {
+    position: absolute;
+    top: 0;
+    right: 0;
+    height: 20px;
+    width: 6px;
+    background-image: url( Images/squareButtonRight.png );
+    background-repeat: no-repeat;
+}
+
+button.square[disabled] {
+    opacity: 0.5;
+}
+
+button.square[disabled] .left {
+    background-image: url( Images/popupLeft.png ) !important;
+}
+
+button.square[disabled] .middle {
+    background-image: url( Images/popupFill.png ) !important;
+}
+
+button.square[disabled] .right {
+    background-image: url( Images/squareButtonRight.png ) !important;
+}
+
+button.square:active .left, button.square.selected .left {
+    background-image: url( Images/popupLeftPressed.png );
+}
+
+button.square:active .middle, button.square.selected .middle {
+    background-image: url( Images/popupFillPressed.png );
+    text-shadow: black 1px -1px 3px;
+}
+
+button.square.selected .middle {
+    font-weight: bold;
+}
+
+button.square:active .right, button.square.selected .right {
+    background-image: url( Images/squareButtonRightPressed.png );
+}
+
+#resize {
+    position: absolute;
+    right: 0;
+    bottom: 0;
+    width: 16px;
+    height: 16px;
+    z-index: 10;
+    -apple-dashboard-region: dashboard-region(resize rectangle);
+    background-image: url( file:///System/Library/WidgetResources/resize.png );
+    background-repeat: no-repeat;
+}
+
+#top {
+    position: absolute;
+    top: 20px;
+    left: 0;
+    right: 0;
+    height: 170px;
+}
+
+#bottom {
+    position: absolute;
+    top: 200px;
+    left: 0;
+    right: 0;
+    bottom: 0;
+}
+
+#bottom .pane {
+    position: absolute;
+    top: 28px;
+    left: 10px;
+    right: 10px;
+    bottom: 12px;
+}
+
+#splitter {
+    position: absolute;
+    top: 190px;
+    left: 5px;
+    right: 5px;
+    height: 10px;
+    cursor: move;
+    z-index: 10;
+    -apple-dashboard-region: dashboard-region(control rectangle);
+}
+
+#splitter hr {
+    position: absolute;
+    top: 4px;
+    left: 0;
+    right: 0;
+    padding: 0;
+    margin: 0;
+    opacity: 0.85;
+}
+
+#tree {
+    background-color: rgba(0,0,0,0.2);
+    border: 1px solid rgba(255,255,255,0.4);
+    position: absolute;
+    top: 26px;  
+    bottom: 4px;
+    left: 10px;
+    right: 10px;
+    -apple-dashboard-region: dashboard-region(control rectangle);
+}
+
+#treeScrollArea {
+    position: absolute;
+    top: 0; 
+    left: 3px;
+    right: 23px;
+    bottom: 0;
+}
+
+#treeOutlineView {
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+}
+
+#treeScrollbar {
+    position: absolute;
+    top: 2px;
+    bottom: 2px;
+    right: 2px;
+    width: 19px;
+    display: block;
+}
+
+button.toggle {
+    width: 8px;
+    height: 8px;
+    border: 0;
+    margin: 0 2px;
+    padding: 0;
+    background-color: transparent;
+}
+
+button.toggle.down {
+    background-image: url( Images/downTriangle.png );
+}
+
+button.toggle.right {
+    background-image: url( Images/rightTriangle.png );
+}
+
+#nodePane {
+    display: -apple-box;
+    -apple-box-orient: vertical;
+}
+
+.infoRow {
+    display: -apple-box;
+    -apple-box-orient: horizontal;
+    margin-top: 2px;
+}
+
+.infoRow.header {
+    margin-top: 6px;
+    border-bottom: 1px solid rgba(255,255,255,0.4);
+    margin-bottom: 3px;
+}
+
+.infoRow .label {
+    display: block;
+    font-weight: bold;
+    text-align: right;
+    padding-right: 3px;
+    width: 100px;
+}
+
+.infoRow .value {
+    display: -apple-box;
+    -apple-box-flex: 1;
+    -apple-dashboard-region: dashboard-region(control rectangle);
+    -apple-user-select: text;
+    white-space: nowrap;
+}
+
+/* This is a workaround for text-overflow: ellipsis not working on boxes. */
+/* http://bugzilla.opendarwin.org/show_bug.cgi?id=5990 */
+.infoRow .value div {
+    width: 100%;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    -apple-user-select: text;
+}
+
+#elementAttributes {
+    display: -apple-box;
+    -apple-box-flex: 3;
+    -apple-box-orient: vertical;
+    min-height: 60px;
+    max-height: 160px;
+}
+
+#nodeContents {
+    display: -apple-box;
+    -apple-box-flex: 12;
+    -apple-box-orient: vertical;
+    overflow: hidden;
+}
+
+#nodeContentsScrollview {
+    -apple-dashboard-region: dashboard-region(control rectangle);
+    -apple-user-select: text;
+    overflow: hidden;
+    font-size: 11px;
+    word-wrap: break-word;
+}
+
+.scrollArea {
+    display: -apple-box;
+    -apple-box-orient: horizontal;
+    -apple-box-flex: 1;
+}
+
+.scrollArea > .view {
+    position: relative;
+    display: -apple-box;
+    -apple-box-flex: 1;
+}
+
+.scrollArea > .view > div {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    overflow: hidden;
+}
+
+.scrollArea > .scrollbar {
+    position: relative;
+    margin-left: 3px;
+    width: 19px;
+    -apple-dashboard-region: dashboard-region(control rectangle);
+}
+
+#stylePane {
+    display: -apple-box;
+    -apple-box-flex: 1;
+    -apple-box-orient: vertical;
+    overflow: hidden;
+}
+
+#styleRules {
+    background-color: rgba(0,0,0,0.2);
+    border: 1px solid rgba(255,255,255,0.4);
+    margin-bottom: 6px;
+}
+
+#styleRulesScrollview {
+    display: -apple-box;
+    -apple-box-orient: vertical;
+    -apple-dashboard-region: dashboard-region(control rectangle);
+    -apple-box-flex: 1;
+}
+
+#styleRulesScrollview > .row {
+    padding: 1px 6px;
+    margin: 2px 0 0 3px;
+}
+
+#styleRulesScrollview > .row.focused {
+    background-color: rgba(128,128,255,0.25);
+    border-radius: 6px;
+    text-shadow: black 1px 2px 3px;
+}
+
+#styleRulesScrollview > .row > .cell {
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+}
+
+#styleRulesScrollview .cell.stylesheet {
+    color: rgba(255,255,255,0.6);
+    font-size: 10px;
+    padding-bottom: 2px;
+}
+
+#styleProperties {
+    background-color: rgba(0,0,0,0.2);
+    border: 1px solid rgba(255,255,255,0.4);
+    -apple-box-flex: 1;
+    -apple-dashboard-region: dashboard-region(control rectangle);
+}
+
+.treeList {
+    padding: 3px 0;
+    margin: 0;
+    list-style-type: none;
+    white-space: nowrap;
+}
+
+.treeList ul {
+    list-style-type: none;
+    -apple-padding-start: 10px;
+}
+
+.treeList li {
+    line-height: 14px;
+    height: 16px;
+    padding-left: 14px;
+    overflow: hidden;
+    text-overflow: ellipsis;
+}
+
+.treeList li button {
+    position: relative;
+    top: 4px;
+    left: 1px;
+    float: left;
+    background-image: url( Images/rightTriangle.png );
+    width: 8px;
+    height: 8px;
+    border: 0;
+    margin: 0 2px;
+    padding: 0;
+    background-color: transparent;
+}
+
+.treeList li.hasChildren {
+    padding-left: 2px;
+}
+
+.treeList li.focused {
+    background-color: rgba(128,128,255,0.25);
+    border-radius: 4px;
+    text-shadow: black 1px 2px 3px;
+}
+
+.treeList li.expanded button {
+    background-image: url( Images/downTriangle.png );
+}
+
+.treeList li span {
+    -apple-user-select: text;
+}
+
+.treeList li .property::after {
+    content: ": ";
+}
+
+.treeList li .value {
+    color: rgb(255,255,180);
+}
+
+.treeList li.implicit .value {
+    color: rgb(180,255,180);
+}
+
+.treeList li .value::after {
+    content: ";";
+}
+
+.treeList li.overloaded {
+    text-decoration: line-through;
+}
diff --git a/WebKit/WebInspector.subproj/webInspector/inspector.html b/WebKit/WebInspector.subproj/webInspector/inspector.html
new file mode 100644 (file)
index 0000000..dc7e5a1
--- /dev/null
@@ -0,0 +1,114 @@
+<!--
+Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1.  Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer. 
+2.  Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution. 
+3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+    its contributors may be used to endorse or promote products derived
+    from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+    <title>Web Inspector</title>
+    <script type="text/javascript" src="inspector.js"></script> 
+    <script type="text/javascript" src="file:///System/Library/WidgetResources/AppleClasses/AppleScrollbar.js"></script>    
+    <script type="text/javascript" src="file:///System/Library/WidgetResources/AppleClasses/AppleScrollArea.js"></script>
+    <style type="text/css">
+        @import "inspector.css";
+    </style>
+</head>
+<body onload="loaded()">
+<div id="body">
+<div id="title"><button class="close" onclick="window.close()"></button>Web Inspector<button class="menu" onmousedown="Inspector.showOptionsMenu()"></button></div>
+<div id="top">
+    <div id="header">
+        <div id="traverse"><button class="square" id="traverseUp" onclick="Inspector.traverseTreeBackward()"><div class="left"></div><div class="middle"><img src="Images/upTriangle.png" /></div></button><button class="square" id="traverseDown" onclick="Inspector.traverseTreeForward()"><img src="Images/popupFillPressed.png" /><div class="middle"><img src="Images/downTriangle.png" /></div><div class="right"></div></button></div>
+        <div id="treePopup">
+            <select size="1" id="realTreePopup" onchange="Inspector.selectNewRoot(this)"></select>
+            <button id="treePopupButton" class="popup"><div class="left"></div><div id="treePopupTitleArea" class="middle"></div><div class="right"></div></button>
+        </div>
+        <div id="searchCount"></div>
+        <input id="search" type="search" autosave="nodeSearch" results="20" placeholder="Search" incremental="incremental" />
+    </div>
+    <div id="tree">
+        <div id="treeScrollArea"><object id="treeOutlineView"><param name="type" value="application/x-inspector-tree" /></object></div>
+        <div id="treeScrollbar"></div>
+    </div>
+</div>
+<div id="splitter" onmousedown="Inspector.resizeTopArea(event)"><hr size="2" /></div>
+<div id="bottom">
+    <div id="tabs">
+        <button class="square selected" id="nodeButton" onclick="switchPane('node')"><div class="left"></div><div class="middle">Node</div></button>
+        <button class="square" id="styleButton" onclick="switchPane('style')"><img src="Images/popupFillPressed.png" /><div class="middle">Style</div></button>
+        <button class="square" id="metricsButton" onclick="switchPane('metrics')"><img src="Images/popupFillPressed.png" /><div class="middle">Metrics</div></button>
+        <button class="square" id="javascriptButton" onclick="switchPane('javascript')"><img src="Images/popupFillPressed.png" /><div class="middle">Properties</div><div class="right"></div></button>
+    </div>
+    <div id="nodePane" class="pane">
+        <div class="infoRow">
+            <span class="label">Node Type:</span>
+            <span class="value" id="nodeType"></span>
+        </div>
+        <div class="infoRow">
+            <span class="label">Node Name:</span>
+            <span class="value" id="nodeName"></span>
+        </div>
+        <div class="infoRow" id="nodeNamespaceRow">
+            <span class="label">Namespace URI:</span>
+            <span class="value"><div id="nodeNamespace"></div></span>
+        </div>
+        <div id="elementAttributes">
+            <div class="infoRow header">
+                <span class="label" style="width: initial">Element Attributes</span>
+            </div>
+            <div class="scrollArea">
+                <div id="elementAttributesScrollview" class="view">(not finished)</div>
+                <div id="elementAttributesScrollbar" class="scrollbar"></div>
+            </div>
+        </div>
+        <div id="nodeContents">
+            <div class="infoRow header">
+                <span class="label" style="width: initial">Markup &amp; Content</span>
+            </div>
+            <div class="scrollArea">
+                <div class="view"><div id="nodeContentsScrollview"></div></div>
+                <div id="nodeContentsScrollbar" class="scrollbar"></div>
+            </div>
+        </div>
+    </div>
+    <div id="metricsPane" class="pane" style="display: none; text-align: center"><br /><br /><br />(not finished)</div>
+    <div id="stylePane" class="pane" style="display: none">
+        <div id="styleRules" class="scrollArea">
+            <div class="view"><div id="styleRulesScrollview"></div></div>
+            <div id="styleRulesScrollbar" class="scrollbar"></div>
+        </div>
+        <div id="styleProperties" class="scrollArea">
+            <div class="view"><div id="stylePropertiesScrollview"><ul class="treeList" id="stylePropertiesTree"></ul></div></div>
+            <div id="stylePropertiesScrollbar" class="scrollbar"></div>
+        </div>
+    </div>
+    <div id="javascriptPane" class="pane" style="display: none; text-align: center"><br /><br /><br />(not finished)</div>
+</div>
+<div id="resize"></div>
+</div>
+</body>
+</html>
diff --git a/WebKit/WebInspector.subproj/webInspector/inspector.js b/WebKit/WebInspector.subproj/webInspector/inspector.js
new file mode 100644 (file)
index 0000000..de2b0aa
--- /dev/null
@@ -0,0 +1,409 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+function loaded()
+{
+    treeScrollbar = new AppleVerticalScrollbar(document.getElementById("treeScrollbar"));
+
+    treeScrollbar.setTrackStart("Images/scrollTrackTop.png", 18);
+    treeScrollbar.setTrackMiddle("Images/scrollTrackMiddle.png");
+    treeScrollbar.setTrackEnd("Images/scrollTrackBottom.png", 18);
+    treeScrollbar.setThumbStart("Images/scrollThumbTop.png", 9);
+    treeScrollbar.setThumbMiddle("Images/scrollThumbMiddle.png");
+    treeScrollbar.setThumbEnd("Images/scrollThumbBottom.png", 9);
+
+    nodeContentsScrollbar = new AppleVerticalScrollbar(document.getElementById("nodeContentsScrollbar"));
+    nodeContentsScrollArea = new AppleScrollArea(document.getElementById("nodeContentsScrollview"), nodeContentsScrollbar);
+
+    nodeContentsScrollbar.setTrackStart("Images/scrollTrackTop.png", 18);
+    nodeContentsScrollbar.setTrackMiddle("Images/scrollTrackMiddle.png");
+    nodeContentsScrollbar.setTrackEnd("Images/scrollTrackBottom.png", 18);
+    nodeContentsScrollbar.setThumbStart("Images/scrollThumbTop.png", 9);
+    nodeContentsScrollbar.setThumbMiddle("Images/scrollThumbMiddle.png");
+    nodeContentsScrollbar.setThumbEnd("Images/scrollThumbBottom.png", 9);
+
+    styleRulesScrollbar = new AppleVerticalScrollbar(document.getElementById("styleRulesScrollbar"));
+    styleRulesScrollArea = new AppleScrollArea(document.getElementById("styleRulesScrollview"), styleRulesScrollbar);
+
+    styleRulesScrollbar.setTrackStart("Images/scrollTrackTop.png", 18);
+    styleRulesScrollbar.setTrackMiddle("Images/scrollTrackMiddle.png");
+    styleRulesScrollbar.setTrackEnd("Images/scrollTrackBottom.png", 18);
+    styleRulesScrollbar.setThumbStart("Images/scrollThumbTop.png", 9);
+    styleRulesScrollbar.setThumbMiddle("Images/scrollThumbMiddle.png");
+    styleRulesScrollbar.setThumbEnd("Images/scrollThumbBottom.png", 9);
+
+    stylePropertiesScrollbar = new AppleVerticalScrollbar(document.getElementById("stylePropertiesScrollbar"));
+    stylePropertiesScrollArea = new AppleScrollArea(document.getElementById("stylePropertiesScrollview"), stylePropertiesScrollbar);
+
+    stylePropertiesScrollbar.setTrackStart("Images/scrollTrackTop.png", 18);
+    stylePropertiesScrollbar.setTrackMiddle("Images/scrollTrackMiddle.png");
+    stylePropertiesScrollbar.setTrackEnd("Images/scrollTrackBottom.png", 18);
+    stylePropertiesScrollbar.setThumbStart("Images/scrollThumbTop.png", 9);
+    stylePropertiesScrollbar.setThumbMiddle("Images/scrollThumbMiddle.png");
+    stylePropertiesScrollbar.setThumbEnd("Images/scrollThumbBottom.png", 9);
+
+    treeScrollbar._getViewToContentRatio = function() {
+        var contentHeight = Inspector.treeViewScrollHeight();
+        var height = document.getElementById("treeScrollArea").offsetHeight;
+        if (contentHeight > height)
+            return height / contentHeight;
+        return 1.0;
+    }
+
+    treeScrollbar._computeTrackOffset = function() { return Inspector.treeViewOffsetTop(); }
+    treeScrollbar._getContentLength = function() { return Inspector.treeViewScrollHeight(); }
+    treeScrollbar._getViewLength = function() { return document.getElementById("treeScrollArea").offsetHeight; }
+    treeScrollbar._canScroll = function() { return true; }
+
+    treeScrollbar.scrollTo = function(pos) {
+        Inspector.treeViewScrollTo(pos);
+        this.verticalHasScrolled();
+    }
+
+    treeScrollbar.verticalHasScrolled = function() {
+        var new_thumb_pos = this._thumbPositionForContentPosition(Inspector.treeViewOffsetTop());
+        this._thumbStart = new_thumb_pos;
+        this._thumb.style.top = new_thumb_pos + "px";
+    }
+
+    // much better AppleScrollArea reveal
+    AppleScrollArea.prototype.reveal = function(node) {
+        var offsetY = 0;
+        var obj = node;
+        do {
+            offsetY += obj.offsetTop;
+            obj = obj.offsetParent;
+        } while (obj && obj != this.content);
+
+        var offsetX = 0;
+        obj = node;
+        do {
+            offsetX += obj.offsetLeft;
+            obj = obj.offsetParent;
+        } while (obj && obj != this.content);
+
+        var top = this.content.scrollTop;
+        var height = this.viewHeight;
+        if ((top + height) < (offsetY + node.clientHeight)) 
+            this.verticalScrollTo(offsetY - height + node.clientHeight);
+        else if (top > offsetY)
+            this.verticalScrollTo(offsetY);
+
+        var left = this.content.scrollLeft;
+        var width = this.viewWidth;
+        if ((left + width) < (offsetX + node.clientWidth)) 
+            this.horizontalScrollTo(offsetX - width + node.clientWidth);
+        else if (left > offsetX)
+            this.horizontalScrollTo(offsetX);
+    };
+
+    window.addEventListener("resize", refreshScrollbars, false);
+}
+
+function refreshScrollbars() {
+    nodeContentsScrollArea.refresh();
+    styleRulesScrollArea.refresh();
+    stylePropertiesScrollArea.refresh();
+}
+
+var tabNames = ["node","metrics","style","javascript"];
+var currentPane = "node";
+var paneUpdateState = new Array();
+
+function switchPane(pane) {
+    currentPane = pane;
+    for (var i = 0; i < tabNames.length; i++) {
+        if (pane == tabNames[i]) {
+            document.getElementById(tabNames[i] + "Pane").style.removeProperty("display");
+            document.getElementById(tabNames[i] + "Button").className = "square selected";
+        } else {
+            document.getElementById(tabNames[i] + "Pane").style.display = "none";
+            document.getElementById(tabNames[i] + "Button").className = "square";
+        }
+    }
+
+    if (!paneUpdateState[pane]) {
+        eval("update" + pane.charAt(0).toUpperCase() + pane.substr(1) + "Pane()");
+        paneUpdateState[pane] = true;
+    }
+}
+
+function nodeTypeName(node) {
+    switch(node.nodeType) {
+        case 1: return "Element";
+        case 2: return "Attribute";
+        case 3: return "Text";
+        case 4: return "Character Data";
+        case 5: return "Entity Reference";
+        case 6: return "Entity";
+        case 7: return "Processing Instruction";
+        case 8: return "Comment";
+        case 9: return "Document";
+        case 10: return "Document Type";
+        case 11: return "Document Fragment";
+        case 12: return "Notation";
+    }
+    return "(unknown)";
+}
+
+function updatePanes() {
+    for (var i = 0; i < tabNames.length; i++)
+        paneUpdateState[tabNames[i]] = false;
+    eval("update" + currentPane.charAt(0).toUpperCase() + currentPane.substr(1) + "Pane()");    
+    paneUpdateState[currentPane] = true;
+}
+
+function updateNodePane() {
+    var focusedNode = Inspector.focusedDOMNode();
+
+    if (focusedNode.nodeType == 3) {
+        document.getElementById("nodeNamespaceRow").style.display = "none";
+        document.getElementById("elementAttributes").style.display = "none";
+        document.getElementById("nodeContents").style.display = null;
+
+        document.getElementById("nodeContentsScrollview").textContent = focusedNode.nodeValue;
+        nodeContentsScrollArea.refresh();
+    } else if (focusedNode.nodeType == 1) {
+        document.getElementById("elementAttributes").style.display = null;
+        document.getElementById("nodeContents").style.display = null;
+
+        if (focusedNode.namespaceURI.length > 0) {
+            document.getElementById("nodeNamespace").textContent = focusedNode.namespaceURI;
+            document.getElementById("nodeNamespaceRow").style.display = null;
+        } else {
+            document.getElementById("nodeNamespaceRow").style.display = "none";
+        }
+
+        document.getElementById("nodeContentsScrollview").innerHTML = "<span class=\"disabled\">Loading...</span>";
+        nodeContentsScrollArea.refresh();
+
+        clearTimeout(nodeUpdateTimeout);
+        nodeUpdateTimeout = setTimeout("delayedNodePaneUpdate()", 250);
+    } else if (focusedNode.nodeType == 9) {
+        document.getElementById("nodeNamespaceRow").style.display = "none";
+        document.getElementById("elementAttributes").style.display = "none";
+        document.getElementById("nodeContents").style.display = "none";
+    }
+
+    document.getElementById("nodeType").textContent = nodeTypeName(focusedNode);
+    document.getElementById("nodeName").textContent = focusedNode.nodeName;
+}
+
+var nodeUpdateTimeout = null;
+function delayedNodePaneUpdate() {
+    var focusedNode = Inspector.focusedDOMNode();
+    var serializer = new XMLSerializer();
+    document.getElementById("nodeContentsScrollview").textContent = serializer.serializeToString(focusedNode);
+    nodeContentsScrollArea.refresh();
+}
+
+var styleRules = null;
+var selectedStyleRuleIndex = 0;
+var styleProperties = null;
+var expandedStyleShorthands = new Array();
+
+function updateStylePane() {
+    var focusedNode = Inspector.focusedDOMNode();
+    var rulesArea = document.getElementById("styleRulesScrollview");
+    var propertiesArea = document.getElementById("stylePropertiesTree");
+
+    rulesArea.innerHTML = "";
+    propertiesArea.innerHTML = "";
+
+    var propertyCount = new Array();
+
+    styleRules = focusedNode.ownerDocument.defaultView.getMatchedCSSRules(focusedNode, "");
+    styleProperties = new Array();
+
+    if (selectedStyleRuleIndex >= styleRules.length)
+        selectedStyleRuleIndex = (styleRules.length - 1);
+
+    for (var i = (styleRules.length - 1); i >= 0; --i) {
+        styleProperties[i] = new Array();
+
+        var row = document.createElement("div");
+        row.className = "row";
+        if (i == selectedStyleRuleIndex)
+            row.className += " focused";
+
+        var cell = document.createElement("div");
+        cell.className = "cell selector";
+        cell.title = styleRules[i].selectorText;
+        cell.textContent = cell.title;
+        row.appendChild(cell);
+
+        cell = document.createElement("div");
+        cell.className = "cell stylesheet";
+        cell.title = styleRules[i].parentStyleSheet.href;
+        cell.textContent = cell.title;
+        row.appendChild(cell);
+
+        row.styleRuleIndex = i;
+        row.addEventListener("click", styleRuleSelect, true);
+
+        var style = styleRules[i].style;
+        var stylePropertyLookup = new Array();
+        for (var j = 0; j < style.length; j++) {
+            var originalProperty = null;
+            var shorthand = style.getPropertyShorthand(style[j]);
+            if (shorthand != null)
+                originalProperty = stylePropertyLookup[shorthand];
+
+            if (originalProperty != null) {
+                originalProperty.subProperties.push(style[j]);
+            } else {
+                originalProperty = new Object();
+                originalProperty.style = style;
+                originalProperty.subProperties = new Array(style[j]);
+                originalProperty.unusedProperties = new Array();
+                if (shorthand != null && propertyCount[shorthand] > 0)
+                    originalProperty.unusedProperties[shorthand] = true;
+                if (shorthand != null) {
+                    if (propertyCount[shorthand] == null)
+                        propertyCount[shorthand] = 1;
+                    else
+                        propertyCount[shorthand]++;
+                }
+                originalProperty.name = (shorthand != null ? shorthand : style[j]);
+                styleProperties[i].push(originalProperty);
+                if (shorthand != null)
+                    stylePropertyLookup[originalProperty.name] = originalProperty;
+            }
+
+            if (propertyCount[style[j]] > 0)
+                originalProperty.unusedProperties[style[j]] = true;
+
+            if (propertyCount[style[j]] == null)
+                propertyCount[style[j]] = 1;
+            else
+                propertyCount[style[j]]++;
+        }
+
+        if (rulesArea.firstChild != null)
+            rulesArea.insertBefore(row, rulesArea.firstChild);
+        else
+            rulesArea.appendChild(row);
+    }
+
+    styleRulesScrollArea.refresh();
+    updateStyleProperties();
+}
+
+function styleRuleSelect(event) {
+    var row = document.getElementById("styleRulesScrollview").firstChild;
+    while (row) {
+        row.className = "row";
+        row = row.nextSibling;
+    }
+
+    row = event.currentTarget;
+    row.className = "row focused";
+
+    selectedStyleRuleIndex = row.styleRuleIndex;
+    updateStyleProperties();
+}
+
+function updateStyleProperties() {
+    var focusedNode = Inspector.focusedDOMNode();
+    var propertiesTree = document.getElementById("stylePropertiesTree");
+    propertiesTree.innerHTML = "";
+
+    for (var i = 0; i < styleProperties[selectedStyleRuleIndex].length; i++) {
+        var prop = styleProperties[selectedStyleRuleIndex][i];
+        var li = document.createElement("li");
+        if (prop.subProperties.length > 1) {
+            li.className = "hasChildren";
+            if (expandedStyleShorthands[prop.name])
+                li.className += " expanded";
+            li.shorthand = prop.name;
+            var button = document.createElement("button");
+            button.addEventListener("click", toggleStyleShorthand, false);
+            li.appendChild(button);
+        }
+
+        if (prop.unusedProperties[prop.name] == true)
+            li.className += " overloaded";
+
+        var span = document.createElement("span");
+        span.className = "property";
+        span.textContent = prop.name;
+        li.appendChild(span);
+
+        span = document.createElement("span");
+        span.className = "value";
+        span.title = prop.style.getPropertyValue(prop.name);
+        span.textContent = span.title;
+        li.appendChild(span);
+
+        propertiesTree.appendChild(li);
+
+        if (prop.subProperties.length > 1) {
+            var subTree = document.createElement("ul");
+            if (!expandedStyleShorthands[prop.name])
+                subTree.style.setProperty("display", "none", "");
+            for (var j = 0; j < prop.subProperties.length; j++) {
+                var li = document.createElement("li");
+                if (prop.style.isPropertyImplicit(prop.subProperties[j]) || prop.style.getPropertyValue(prop.subProperties[j]) == "initial")
+                    li.className = "implicit";
+                if (prop.unusedProperties[prop.subProperties[j]] == true)
+                    li.className += " overloaded";
+                var span = document.createElement("span");
+                span.className = "property";
+                span.textContent = prop.subProperties[j];
+                li.appendChild(span);
+
+                span = document.createElement("span");
+                span.className = "value";
+                span.title = prop.style.getPropertyValue(prop.subProperties[j]);
+                span.textContent = span.title;
+                li.appendChild(span);
+
+                subTree.appendChild(li);
+            }
+
+            propertiesTree.appendChild(subTree);
+        }
+    }
+
+    stylePropertiesScrollArea.refresh();
+}
+
+function toggleStyleShorthand(event) {
+    var li = event.currentTarget.parentNode;
+    if (li.className.indexOf("expanded") != -1) {
+        li.className = li.className.replace(/ expanded/, "");
+        li.nextSibling.style.setProperty("display", "none", "");
+        expandedStyleShorthands[li.shorthand] = false;
+    } else {
+        li.className += " expanded";
+        li.nextSibling.style.removeProperty("display");
+        expandedStyleShorthands[li.shorthand] = true;
+    }
+
+    stylePropertiesScrollArea.refresh();
+}
index 3618b9b7443518cd6fe9ef398cff15628b00e7d2..afab72b87d3c3728d9db10c836ded9180a2a3a3e 100644 (file)
@@ -7,6 +7,18 @@
        objects = {
 
 /* Begin PBXBuildFile section */
+               1C68F667095B5FC100C2984E /* webInspector in Resources */ = {isa = PBXBuildFile; fileRef = 1C68F640095B5FC100C2984E /* webInspector */; };
+               1C68F668095B5FC100C2984E /* WebInspector.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C68F65C095B5FC100C2984E /* WebInspector.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               1C68F669095B5FC100C2984E /* WebInspector.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C68F65D095B5FC100C2984E /* WebInspector.m */; };
+               1C68F66A095B5FC100C2984E /* WebInspectorInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C68F65E095B5FC100C2984E /* WebInspectorInternal.h */; };
+               1C68F66B095B5FC100C2984E /* WebInspectorOutlineView.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C68F65F095B5FC100C2984E /* WebInspectorOutlineView.h */; };
+               1C68F66C095B5FC100C2984E /* WebInspectorOutlineView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C68F660095B5FC100C2984E /* WebInspectorOutlineView.m */; };
+               1C68F66D095B5FC100C2984E /* WebInspectorPanel.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C68F661095B5FC100C2984E /* WebInspectorPanel.h */; };
+               1C68F66E095B5FC100C2984E /* WebInspectorPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C68F662095B5FC100C2984E /* WebInspectorPanel.m */; };
+               1C68F66F095B5FC100C2984E /* WebNodeHighlight.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C68F663095B5FC100C2984E /* WebNodeHighlight.h */; };
+               1C68F670095B5FC100C2984E /* WebNodeHighlight.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C68F664095B5FC100C2984E /* WebNodeHighlight.m */; };
+               1C68F671095B5FC100C2984E /* WebNodeHighlightView.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C68F665095B5FC100C2984E /* WebNodeHighlightView.h */; };
+               1C68F672095B5FC100C2984E /* WebNodeHighlightView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C68F666095B5FC100C2984E /* WebNodeHighlightView.m */; };
                220398770922D816009C3FFC /* WebBaseNetscapePluginViewInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 2203984A0922D765009C3FFC /* WebBaseNetscapePluginViewInternal.h */; settings = {ATTRIBUTES = (); }; };
                224100F3091818D900D2D266 /* WebPluginsPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 224100F2091818D900D2D266 /* WebPluginsPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
                224100F90918190100D2D266 /* WebPluginsPrivate.m in Sources */ = {isa = PBXBuildFile; fileRef = 224100F80918190100D2D266 /* WebPluginsPrivate.m */; };
 /* End PBXBuildStyle section */
 
 /* Begin PBXFileReference section */
+               1C68F640095B5FC100C2984E /* webInspector */ = {isa = PBXFileReference; lastKnownFileType = folder; name = webInspector; path = WebInspector.subproj/webInspector; sourceTree = SOURCE_ROOT; };
+               1C68F65C095B5FC100C2984E /* WebInspector.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; name = WebInspector.h; path = WebInspector.subproj/WebInspector.h; sourceTree = SOURCE_ROOT; tabWidth = 8; usesTabs = 0; };
+               1C68F65D095B5FC100C2984E /* WebInspector.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; name = WebInspector.m; path = WebInspector.subproj/WebInspector.m; sourceTree = SOURCE_ROOT; tabWidth = 8; usesTabs = 0; };
+               1C68F65E095B5FC100C2984E /* WebInspectorInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; name = WebInspectorInternal.h; path = WebInspector.subproj/WebInspectorInternal.h; sourceTree = SOURCE_ROOT; tabWidth = 8; usesTabs = 0; };
+               1C68F65F095B5FC100C2984E /* WebInspectorOutlineView.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; name = WebInspectorOutlineView.h; path = WebInspector.subproj/WebInspectorOutlineView.h; sourceTree = SOURCE_ROOT; tabWidth = 8; usesTabs = 0; };
+               1C68F660095B5FC100C2984E /* WebInspectorOutlineView.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; name = WebInspectorOutlineView.m; path = WebInspector.subproj/WebInspectorOutlineView.m; sourceTree = SOURCE_ROOT; tabWidth = 8; usesTabs = 0; };
+               1C68F661095B5FC100C2984E /* WebInspectorPanel.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; name = WebInspectorPanel.h; path = WebInspector.subproj/WebInspectorPanel.h; sourceTree = SOURCE_ROOT; tabWidth = 8; usesTabs = 0; };
+               1C68F662095B5FC100C2984E /* WebInspectorPanel.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; name = WebInspectorPanel.m; path = WebInspector.subproj/WebInspectorPanel.m; sourceTree = SOURCE_ROOT; tabWidth = 8; usesTabs = 0; };
+               1C68F663095B5FC100C2984E /* WebNodeHighlight.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; name = WebNodeHighlight.h; path = WebInspector.subproj/WebNodeHighlight.h; sourceTree = SOURCE_ROOT; tabWidth = 8; usesTabs = 0; wrapsLines = 0; };
+               1C68F664095B5FC100C2984E /* WebNodeHighlight.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; name = WebNodeHighlight.m; path = WebInspector.subproj/WebNodeHighlight.m; sourceTree = SOURCE_ROOT; tabWidth = 8; usesTabs = 0; };
+               1C68F665095B5FC100C2984E /* WebNodeHighlightView.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; name = WebNodeHighlightView.h; path = WebInspector.subproj/WebNodeHighlightView.h; sourceTree = SOURCE_ROOT; tabWidth = 8; usesTabs = 0; };
+               1C68F666095B5FC100C2984E /* WebNodeHighlightView.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; name = WebNodeHighlightView.m; path = WebInspector.subproj/WebNodeHighlightView.m; sourceTree = SOURCE_ROOT; tabWidth = 8; usesTabs = 0; };
                2203984A0922D765009C3FFC /* WebBaseNetscapePluginViewInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebBaseNetscapePluginViewInternal.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                224100F2091818D900D2D266 /* WebPluginsPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebPluginsPrivate.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                224100F80918190100D2D266 /* WebPluginsPrivate.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = WebPluginsPrivate.m; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                                F5EBC45202134BB601CA1520 /* Plugins */,
                                F5B36B400281DE87018635CB /* WebCore Support */,
                                9C7CABBB0190A37C0ECA16EA /* WebView */,
+                               1C68F63F095B5F9C00C2984E /* Web Inspector */,
                                F7EBEE5903F9DB2203CA0DE6 /* Carbon Support */,
                                089C1665FE841158C02AAC07 /* Resources */,
                                0867D69AFE84028FC02AAC07 /* Frameworks and Libraries */,
                        name = Resources;
                        sourceTree = SOURCE_ROOT;
                };
+               1C68F63F095B5F9C00C2984E /* Web Inspector */ = {
+                       isa = PBXGroup;
+                       children = (
+                               1C68F640095B5FC100C2984E /* webInspector */,
+                               1C68F65C095B5FC100C2984E /* WebInspector.h */,
+                               1C68F65D095B5FC100C2984E /* WebInspector.m */,
+                               1C68F65E095B5FC100C2984E /* WebInspectorInternal.h */,
+                               1C68F65F095B5FC100C2984E /* WebInspectorOutlineView.h */,
+                               1C68F660095B5FC100C2984E /* WebInspectorOutlineView.m */,
+                               1C68F661095B5FC100C2984E /* WebInspectorPanel.h */,
+                               1C68F662095B5FC100C2984E /* WebInspectorPanel.m */,
+                               1C68F663095B5FC100C2984E /* WebNodeHighlight.h */,
+                               1C68F664095B5FC100C2984E /* WebNodeHighlight.m */,
+                               1C68F665095B5FC100C2984E /* WebNodeHighlightView.h */,
+                               1C68F666095B5FC100C2984E /* WebNodeHighlightView.m */,
+                       );
+                       name = "Web Inspector";
+                       path = WebView.subproj;
+                       sourceTree = "<group>";
+               };
                254DC334016E1D3F0ECA149E /* Misc */ = {
                        isa = PBXGroup;
                        children = (
                                22F219CC08D236730030E078 /* WebBackForwardListPrivate.h in Headers */,
                                ABDDF20D08EB0DDC001E1241 /* WebDownloadInternal.h in Headers */,
                                224100F3091818D900D2D266 /* WebPluginsPrivate.h in Headers */,
+                               1C68F668095B5FC100C2984E /* WebInspector.h in Headers */,
+                               1C68F66A095B5FC100C2984E /* WebInspectorInternal.h in Headers */,
+                               1C68F66B095B5FC100C2984E /* WebInspectorOutlineView.h in Headers */,
+                               1C68F66D095B5FC100C2984E /* WebInspectorPanel.h in Headers */,
+                               1C68F66F095B5FC100C2984E /* WebNodeHighlight.h in Headers */,
+                               1C68F671095B5FC100C2984E /* WebNodeHighlightView.h in Headers */,
                                65C7F42C0979DE640022E453 /* WebPageBridge.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                                939810B80824BF01008DF038 /* missing_image.tiff in Resources */,
                                939810B90824BF01008DF038 /* WebViewEditingContextMenu.nib in Resources */,
                                939810BA0824BF01008DF038 /* IDNScriptWhiteList.txt in Resources */,
+                               1C68F667095B5FC100C2984E /* webInspector in Resources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                7E6FEF0208985A3E00C44C3F /* WebDefaultScriptDebugDelegate.m in Sources */,
                                7E6FEF0908985A7200C44C3F /* WebScriptDebugDelegate.m in Sources */,
                                224100F90918190100D2D266 /* WebPluginsPrivate.m in Sources */,
+                               1C68F669095B5FC100C2984E /* WebInspector.m in Sources */,
+                               1C68F66C095B5FC100C2984E /* WebInspectorOutlineView.m in Sources */,
+                               1C68F66E095B5FC100C2984E /* WebInspectorPanel.m in Sources */,
+                               1C68F670095B5FC100C2984E /* WebNodeHighlight.m in Sources */,
+                               1C68F672095B5FC100C2984E /* WebNodeHighlightView.m in Sources */,
                                65C7F42D0979DE640022E453 /* WebPageBridge.m in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
index 5549a393c473cceb9a8cbb32568e3eb899f22815..4fcfff3f1eee68d454c93d421eb6db373d7c37fa 100644 (file)
@@ -40,6 +40,8 @@
 - (void)webView:(WebView *)sender drawFooterInRect:(NSRect)rect;
 - (void)webView:(WebView *)webView addMessageToConsole:(NSDictionary *)message;
 
+- (NSView *)webView:(WebView *)webView plugInViewWithArguments:(NSDictionary *)arguments;
+
 // regions is an dictionary whose keys are regions label and values are arrays of WebDashboardRegions.
 - (void)webView:(WebView *)webView dashboardRegionsChanged:(NSDictionary *)regions;
 
index e20175fb216841850371f8a8354b4a6635f1f9f2..cd3d59b2e2c612d118bb7d20fd574095f7fd9c14 100644 (file)
@@ -60,6 +60,7 @@
 #import <WebKit/WebIconDatabase.h>
 #import <WebKit/WebKitErrors.h>
 #import <WebKit/WebKitLogging.h>
+#import <WebKit/WebLocalizableStrings.h>
 #import <WebKit/WebKitNSStringExtras.h>
 #import <WebKit/WebKitStatisticsPrivate.h>
 #import <WebKit/WebNSDataExtras.h>
@@ -82,6 +83,7 @@
 #import <WebKit/WebTextRenderer.h>
 #import <WebKit/WebUIDelegate.h>
 #import <WebKit/WebUIDelegatePrivate.h>
+#import <WebKit/WebInspector.h>
 #import <WebKitSystemInterface.h>
 
 #import <WebCore/WebCoreEncodings.h>
@@ -733,6 +735,27 @@ static bool debugWidget = true;
         }
     }
 
+#ifdef NDEBUG
+    BOOL enableInspectElement = [[NSUserDefaults standardUserDefaults] boolForKey:@"WebKitEnableInspectElementContextMenuItem"];
+#else
+    BOOL enableInspectElement = YES; // always enable in debug builds
+#endif
+
+    // optionally add the Inspect Element menu item it if preference is set or in debug builds
+    // and only showing the menu item if we are working with a WebHTMLView
+    WebFrame *webFrame = [element objectForKey:WebElementFrameKey];
+    if (enableInspectElement && [[[webFrame frameView] documentView] isKindOfClass:[WebHTMLView class]]) {
+        if (!menu)
+            menu = [[[NSMenu alloc] init] autorelease];
+        else if ([menu numberOfItems])
+            [menu addItem:[NSMenuItem separatorItem]];
+        NSMenuItem *menuItem = [[[NSMenuItem alloc] init] autorelease];
+        [menuItem setAction:@selector(_inspectElement:)];
+        [menuItem setTitle:UI_STRING("Inspect Element", "Inspect Element context menu item")];
+        [menuItem setRepresentedObject:element];
+        [menu addItem:menuItem];
+    }
+
     return menu;
 }
 
@@ -2338,6 +2361,28 @@ static WebFrame *incrementFrame(WebFrame *curr, BOOL forward, BOOL wrapFlag)
     _private->dragCaretBridge = nil;
 }
 
+- (void)_inspectElement:(id)sender
+{
+    NSDictionary *element = [sender representedObject];
+    WebFrame *frame = [element objectForKey:WebElementFrameKey];
+    DOMNode *node = [element objectForKey:WebElementDOMNodeKey];
+    if (!node || !frame)
+        return;
+
+    if ([node nodeType] != DOM_ELEMENT_NODE || [node nodeType] != DOM_DOCUMENT_NODE)
+        node = [node parentNode];
+
+    WebInspector *inspector = [WebInspector sharedWebInspector];
+    [inspector setWebFrame:frame];
+    [inspector setFocusedDOMNode:node];
+
+    node = [node parentNode];
+    node = [node parentNode];
+    if (node) // set the root node to something retivally close to the focused node
+        [inspector setRootDOMNode:node];
+
+    [inspector showWindow:nil];
+}
 @end
 
 @implementation WebView (WebIBActions)