Changeset 53941 in webkit


Ignore:
Timestamp:
Jan 27, 2010 10:36:54 AM (14 years ago)
Author:
pfeldman@chromium.org
Message:

2010-01-27 Pavel Feldman <pfeldman@chromium.org>

Reviewed by Timothy Hatcher.

Web Inspector: migrate from SourceFrame to SourceFrame2.

https://bugs.webkit.org/show_bug.cgi?id=34171

  • WebCore.gypi:
  • WebCore.vcproj/WebCore.vcproj:
  • bindings/js/JSInspectorFrontendHostCustom.cpp:
  • bindings/v8/custom/V8InspectorFrontendHostCustom.cpp:
  • inspector/InspectorFrontendHost.cpp:
  • inspector/InspectorFrontendHost.h:
  • inspector/InspectorFrontendHost.idl:
  • inspector/front-end/InspectorBackendStub.js:
  • inspector/front-end/InspectorFrontendHostStub.js:
  • inspector/front-end/ResourceView.js: (WebInspector.ResourceView.prototype._innerSelectContentTab):
  • inspector/front-end/ResourcesPanel.js: (WebInspector.getResourceContent):
  • inspector/front-end/ScriptView.js: (WebInspector.ScriptView): (WebInspector.ScriptView.prototype.setupSourceFrameIfNeeded):
  • inspector/front-end/ScriptsPanel.js: (WebInspector.ScriptsPanel.prototype._sidebarResizeDrag):
  • inspector/front-end/SourceFrame.js: (WebInspector.SourceFrame): (WebInspector.SourceFrame.prototype.set executionLine): (WebInspector.SourceFrame.prototype.revealLine): (WebInspector.SourceFrame.prototype.addBreakpoint): (WebInspector.SourceFrame.prototype.removeBreakpoint): (WebInspector.SourceFrame.prototype.addMessage): (WebInspector.SourceFrame.prototype.clearMessages): (WebInspector.SourceFrame.prototype.sizeToFitContentHeight): (WebInspector.SourceFrame.prototype.setContent): (WebInspector.SourceFrame.prototype.findSearchMatches): (WebInspector.SourceFrame.prototype._collectRegexMatches): (WebInspector.SourceFrame.prototype.setSelection): (WebInspector.SourceFrame.prototype._incrementMessageRepeatCount): (WebInspector.SourceFrame.prototype._addExistingMessagesToSource): (WebInspector.SourceFrame.prototype._addMessageToSource): (WebInspector.SourceFrame.prototype._addExistingBreakpointsToSource): (WebInspector.SourceFrame.prototype._addBreakpointToSource): (WebInspector.SourceFrame.prototype._removeBreakpointFromSource): (WebInspector.SourceFrame.prototype._contextMenu.addConditionalBreakpoint): (WebInspector.SourceFrame.prototype._contextMenu): (WebInspector.SourceFrame.prototype._toggleBreakpoint): (WebInspector.SourceFrame.prototype._editBreakpointCondition.committed): (WebInspector.SourceFrame.prototype._editBreakpointCondition.dismissed): (WebInspector.SourceFrame.prototype._editBreakpointCondition): (WebInspector.SourceFrame.prototype._showBreakpointConditionPopup): (WebInspector.SourceFrame.prototype._createConditionElement): (WebInspector.SourceFrame.prototype._keyDown): (WebInspector.SourceFrame.prototype._evalSelectionInCallFrame): (WebInspector.SourceFrame.prototype._breakpointChanged): (WebInspector.SourceFrame.prototype.resize): (WebInspector.BreakpointLineNumberDecorator): (WebInspector.BreakpointLineNumberDecorator.prototype.decorate): (WebInspector.BreakpointLineNumberDecorator.prototype._paintBreakpoint): (WebInspector.BreakpointLineNumberDecorator.prototype._paintProgramCounter): (WebInspector.BreakpointLineNumberDecorator.prototype.mouseDown): (WebInspector.BreakpointLineNumberDecorator.prototype.contextMenu): (WebInspector.ExecutionLineDecorator): (WebInspector.ExecutionLineDecorator.prototype.decorate):
  • inspector/front-end/SourceFrame2.js: Removed.
  • inspector/front-end/SourceView.js: (WebInspector.SourceView): (WebInspector.SourceView.prototype.show): (WebInspector.SourceView.prototype.resize): (WebInspector.SourceView.prototype.setupSourceFrameIfNeeded): (WebInspector.SourceView.prototype._contentLoaded): (WebInspector.SourceView.prototype.performSearch.findSearchMatches): (WebInspector.SourceView.prototype.performSearch): (WebInspector.SourceView.prototype._jumpToSearchResult): (WebInspector.SourceView.prototype._sourceFrameSetupFinished):
  • inspector/front-end/TextEditor.js: (WebInspector.TextEditor.prototype._mouseDown): (WebInspector.TextEditor.prototype._copy.delayCopy): (WebInspector.TextEditor.prototype._copy): (WebInspector.TextEditor.prototype._cut):
  • inspector/front-end/WebKit.qrc:
  • inspector/front-end/inspector.html:
Location:
trunk/WebCore
Files:
1 deleted
20 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r53940 r53941  
     12010-01-27  Pavel Feldman  <pfeldman@chromium.org>
     2
     3        Reviewed by Timothy Hatcher.
     4
     5        Web Inspector: migrate from SourceFrame to SourceFrame2.
     6
     7        https://bugs.webkit.org/show_bug.cgi?id=34171
     8
     9        * WebCore.gypi:
     10        * WebCore.vcproj/WebCore.vcproj:
     11        * bindings/js/JSInspectorFrontendHostCustom.cpp:
     12        * bindings/v8/custom/V8InspectorFrontendHostCustom.cpp:
     13        * inspector/InspectorFrontendHost.cpp:
     14        * inspector/InspectorFrontendHost.h:
     15        * inspector/InspectorFrontendHost.idl:
     16        * inspector/front-end/InspectorBackendStub.js:
     17        * inspector/front-end/InspectorFrontendHostStub.js:
     18        * inspector/front-end/ResourceView.js:
     19        (WebInspector.ResourceView.prototype._innerSelectContentTab):
     20        * inspector/front-end/ResourcesPanel.js:
     21        (WebInspector.getResourceContent):
     22        * inspector/front-end/ScriptView.js:
     23        (WebInspector.ScriptView):
     24        (WebInspector.ScriptView.prototype.setupSourceFrameIfNeeded):
     25        * inspector/front-end/ScriptsPanel.js:
     26        (WebInspector.ScriptsPanel.prototype._sidebarResizeDrag):
     27        * inspector/front-end/SourceFrame.js:
     28        (WebInspector.SourceFrame):
     29        (WebInspector.SourceFrame.prototype.set executionLine):
     30        (WebInspector.SourceFrame.prototype.revealLine):
     31        (WebInspector.SourceFrame.prototype.addBreakpoint):
     32        (WebInspector.SourceFrame.prototype.removeBreakpoint):
     33        (WebInspector.SourceFrame.prototype.addMessage):
     34        (WebInspector.SourceFrame.prototype.clearMessages):
     35        (WebInspector.SourceFrame.prototype.sizeToFitContentHeight):
     36        (WebInspector.SourceFrame.prototype.setContent):
     37        (WebInspector.SourceFrame.prototype.findSearchMatches):
     38        (WebInspector.SourceFrame.prototype._collectRegexMatches):
     39        (WebInspector.SourceFrame.prototype.setSelection):
     40        (WebInspector.SourceFrame.prototype._incrementMessageRepeatCount):
     41        (WebInspector.SourceFrame.prototype._addExistingMessagesToSource):
     42        (WebInspector.SourceFrame.prototype._addMessageToSource):
     43        (WebInspector.SourceFrame.prototype._addExistingBreakpointsToSource):
     44        (WebInspector.SourceFrame.prototype._addBreakpointToSource):
     45        (WebInspector.SourceFrame.prototype._removeBreakpointFromSource):
     46        (WebInspector.SourceFrame.prototype._contextMenu.addConditionalBreakpoint):
     47        (WebInspector.SourceFrame.prototype._contextMenu):
     48        (WebInspector.SourceFrame.prototype._toggleBreakpoint):
     49        (WebInspector.SourceFrame.prototype._editBreakpointCondition.committed):
     50        (WebInspector.SourceFrame.prototype._editBreakpointCondition.dismissed):
     51        (WebInspector.SourceFrame.prototype._editBreakpointCondition):
     52        (WebInspector.SourceFrame.prototype._showBreakpointConditionPopup):
     53        (WebInspector.SourceFrame.prototype._createConditionElement):
     54        (WebInspector.SourceFrame.prototype._keyDown):
     55        (WebInspector.SourceFrame.prototype._evalSelectionInCallFrame):
     56        (WebInspector.SourceFrame.prototype._breakpointChanged):
     57        (WebInspector.SourceFrame.prototype.resize):
     58        (WebInspector.BreakpointLineNumberDecorator):
     59        (WebInspector.BreakpointLineNumberDecorator.prototype.decorate):
     60        (WebInspector.BreakpointLineNumberDecorator.prototype._paintBreakpoint):
     61        (WebInspector.BreakpointLineNumberDecorator.prototype._paintProgramCounter):
     62        (WebInspector.BreakpointLineNumberDecorator.prototype.mouseDown):
     63        (WebInspector.BreakpointLineNumberDecorator.prototype.contextMenu):
     64        (WebInspector.ExecutionLineDecorator):
     65        (WebInspector.ExecutionLineDecorator.prototype.decorate):
     66        * inspector/front-end/SourceFrame2.js: Removed.
     67        * inspector/front-end/SourceView.js:
     68        (WebInspector.SourceView):
     69        (WebInspector.SourceView.prototype.show):
     70        (WebInspector.SourceView.prototype.resize):
     71        (WebInspector.SourceView.prototype.setupSourceFrameIfNeeded):
     72        (WebInspector.SourceView.prototype._contentLoaded):
     73        (WebInspector.SourceView.prototype.performSearch.findSearchMatches):
     74        (WebInspector.SourceView.prototype.performSearch):
     75        (WebInspector.SourceView.prototype._jumpToSearchResult):
     76        (WebInspector.SourceView.prototype._sourceFrameSetupFinished):
     77        * inspector/front-end/TextEditor.js:
     78        (WebInspector.TextEditor.prototype._mouseDown):
     79        (WebInspector.TextEditor.prototype._copy.delayCopy):
     80        (WebInspector.TextEditor.prototype._copy):
     81        (WebInspector.TextEditor.prototype._cut):
     82        * inspector/front-end/WebKit.qrc:
     83        * inspector/front-end/inspector.html:
     84
    1852010-01-27  Dominik Röttsches  <dominik.roettsches@access-company.com>
    286
  • trunk/WebCore/WebCore.gypi

    r53931 r53941  
    37343734            'inspector/front-end/SourceCSSTokenizer.js',
    37353735            'inspector/front-end/SourceFrame.js',
    3736             'inspector/front-end/SourceFrame2.js',
    37373736            'inspector/front-end/SourceHTMLTokenizer.js',
    37383737            'inspector/front-end/SourceJavaScriptTokenizer.js',
  • trunk/WebCore/WebCore.vcproj/WebCore.vcproj

    r53915 r53941  
    4292142921                                </File>
    4292242922                                <File
    42923                                         RelativePath="..\inspector\front-end\SourceFrame2.js"
    42924                                         >
    42925                                 </File>
    42926                                 <File
    4292742923                                        RelativePath="..\inspector\front-end\SourceHTMLTokenizer.js"
    4292842924                                        >
  • trunk/WebCore/bindings/js/JSInspectorFrontendHostCustom.cpp

    r51993 r53941  
    3737
    3838#include "ContextMenuItem.h"
    39 #include "ExceptionCode.h"
    40 #include "Frame.h"
    4139#include "InspectorController.h"
    4240#include "InspectorFrontendHost.h"
    4341#include "JSEvent.h"
    44 #include "JSNode.h"
    45 #include "JSRange.h"
    4642#include "MouseEvent.h"
    47 #include "Node.h"
    48 #include "Page.h"
    49 #include "TextIterator.h"
    50 #include "VisiblePosition.h"
    5143#include <runtime/JSArray.h>
    5244#include <runtime/JSLock.h>
     
    5749
    5850namespace WebCore {
    59 
    60 JSValue JSInspectorFrontendHost::search(ExecState* exec, const ArgList& args)
    61 {
    62     if (args.size() < 2)
    63         return jsUndefined();
    64 
    65     Node* node = toNode(args.at(0));
    66     if (!node)
    67         return jsUndefined();
    68 
    69     String target = args.at(1).toString(exec);
    70     if (exec->hadException())
    71         return jsUndefined();
    72 
    73     MarkedArgumentBuffer result;
    74     RefPtr<Range> searchRange(rangeOfContents(node));
    75 
    76     ExceptionCode ec = 0;
    77     do {
    78         RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, true, false));
    79         if (resultRange->collapsed(ec))
    80             break;
    81 
    82         // A non-collapsed result range can in some funky whitespace cases still not
    83         // advance the range's start position (4509328). Break to avoid infinite loop.
    84         VisiblePosition newStart = endVisiblePosition(resultRange.get(), DOWNSTREAM);
    85         if (newStart == startVisiblePosition(searchRange.get(), DOWNSTREAM))
    86             break;
    87 
    88         result.append(toJS(exec, resultRange.get()));
    89 
    90         setStart(searchRange.get(), newStart);
    91     } while (true);
    92 
    93     return constructArray(exec, result);
    94 }
    9551
    9652JSValue JSInspectorFrontendHost::showContextMenu(ExecState* execState, const ArgList& args)
  • trunk/WebCore/bindings/v8/custom/V8InspectorFrontendHostCustom.cpp

    r53271 r53941  
    3232#include "V8InspectorFrontendHost.h"
    3333
    34 #include "ExceptionCode.h"
    3534#include "InspectorController.h"
    3635#include "InspectorFrontendHost.h"
    37 #include "Node.h"
    38 #include "Range.h"
    39 #include "Page.h"
    40 #include "TextIterator.h"
    41 #include "VisiblePosition.h"
    4236
    4337#include "V8Binding.h"
    4438#include "V8CustomBinding.h"
    45 #include "V8Node.h"
    4639#include "V8Proxy.h"
    4740
    4841namespace WebCore {
    49 
    50 v8::Handle<v8::Value> V8InspectorFrontendHost::searchCallback(const v8::Arguments& args)
    51 {
    52     INC_STATS("InspectorFrontendHost.search()");
    53 
    54     if (args.Length() < 2)
    55         return v8::Undefined();
    56 
    57     Node* node = V8Node::toNative(v8::Handle<v8::Object>::Cast(args[0]));
    58     if (!node)
    59         return v8::Undefined();
    60 
    61     String target = toWebCoreStringWithNullCheck(args[1]);
    62     if (target.isEmpty())
    63         return v8::Undefined();
    64 
    65     v8::Local<v8::Array> result = v8::Array::New();
    66     RefPtr<Range> searchRange(rangeOfContents(node));
    67 
    68     ExceptionCode ec = 0;
    69     int index = 0;
    70     do {
    71         RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, true, false));
    72         if (resultRange->collapsed(ec))
    73             break;
    74 
    75         // A non-collapsed result range can in some funky whitespace cases still not
    76         // advance the range's start position (4509328). Break to avoid infinite loop.
    77         VisiblePosition newStart = endVisiblePosition(resultRange.get(), DOWNSTREAM);
    78         if (newStart == startVisiblePosition(searchRange.get(), DOWNSTREAM))
    79             break;
    80 
    81         result->Set(v8::Number::New(index++), V8DOMWrapper::convertToV8Object(V8ClassIndex::RANGE, resultRange.release()));
    82 
    83         setStart(searchRange.get(), newStart);
    84     } while (true);
    85 
    86     return result;
    87 }
    8842
    8943v8::Handle<v8::Value> V8InspectorFrontendHost::showContextMenuCallback(const v8::Arguments& args)
  • trunk/WebCore/inspector/InspectorFrontendHost.cpp

    r53855 r53941  
    4646#include "InspectorResource.h"
    4747#include "Page.h"
     48#include "Pasteboard.h"
    4849
    4950#include <wtf/RefPtr.h>
     
    134135}
    135136
    136 
    137137const String& InspectorFrontendHost::port() const
    138138{
     
    150150}
    151151
    152 // FIXME: Remove this once migrated to SourceFrame2.
    153 void InspectorFrontendHost::addResourceSourceToFrame(long identifier, Node* frame)
     152void InspectorFrontendHost::copyText(const String& text)
    154153{
    155     if (!m_inspectorController)
    156         return;
    157     RefPtr<InspectorResource> resource = m_inspectorController->resources().get(identifier);
    158     if (resource) {
    159         String sourceString = resource->sourceString();
    160         if (!sourceString.isEmpty())
    161             addSourceToFrame(resource->mimeType(), sourceString, frame);
    162     }
    163 }
    164 
    165 // FIXME: Remove this once migrated to SourceFrame2.
    166 bool InspectorFrontendHost::addSourceToFrame(const String& mimeType, const String& source, Node* frameNode)
    167 {
    168     ASSERT_ARG(frameNode, frameNode);
    169 
    170     if (!frameNode)
    171         return false;
    172 
    173     if (!frameNode->attached()) {
    174         ASSERT_NOT_REACHED();
    175         return false;
    176     }
    177 
    178     ASSERT(frameNode->isElementNode());
    179     if (!frameNode->isElementNode())
    180         return false;
    181 
    182     Element* element = static_cast<Element*>(frameNode);
    183     ASSERT(element->isFrameOwnerElement());
    184     if (!element->isFrameOwnerElement())
    185         return false;
    186 
    187     HTMLFrameOwnerElement* frameOwner = static_cast<HTMLFrameOwnerElement*>(element);
    188     ASSERT(frameOwner->contentFrame());
    189     if (!frameOwner->contentFrame())
    190         return false;
    191 
    192     FrameLoader* loader = frameOwner->contentFrame()->loader();
    193 
    194     loader->setResponseMIMEType(mimeType);
    195     loader->begin();
    196     loader->write(source);
    197     loader->end();
    198 
    199     return true;
     154    Pasteboard::generalPasteboard()->writePlainText(text);
    200155}
    201156
  • trunk/WebCore/inspector/InspectorFrontendHost.h

    r53855 r53941  
    7474    const String& port() const;
    7575
    76     // FIXME: Remove these once migrated to SourceFrame2.
    77     void addResourceSourceToFrame(long identifier, Node* frame);
    78     bool addSourceToFrame(const String& mimeType, const String& source, Node* frame);
     76    void copyText(const String& text);
    7977
    8078    // Called from [Custom] implementations.
  • trunk/WebCore/inspector/InspectorFrontendHost.idl

    r53855 r53941  
    4747        DOMString port();
    4848
    49         // FIXME: Remove these once migrated to SourceFrame2.
    50         void addResourceSourceToFrame(in long identifier, in Node frame);
    51         boolean addSourceToFrame(in DOMString mimeType, in DOMString sourceValue, in Node frame);
     49        void copyText(in DOMString text);
    5250
    53         [Custom] void search(in Node node, in DOMString query);
    5451        [Custom] void showContextMenu(in MouseEvent event, in DOMObject items);
    5552    };
  • trunk/WebCore/inspector/front-end/InspectorBackendStub.js

    r53855 r53941  
    101101    },
    102102
    103     addResourceSourceToFrame: function(identifier, element)
    104     {
    105     },
    106 
    107     addSourceToFrame: function(mimeType, source, element)
    108     {
    109         return false;
    110     },
    111 
    112     // FIXME: remove once migrated to SourceFrame2.
    113103    getResourceContent: function(callId, identifier)
    114104    {
    115105        WebInspector.didGetResourceContent(callId, "");
    116     },
    117 
    118     // FIXME: remove once migrated to SourceFrame2.
    119     getResourceDocumentNode: function(identifier)
    120     {
    121         return undefined;
    122106    },
    123107
  • trunk/WebCore/inspector/front-end/InspectorFrontendHostStub.js

    r53855 r53941  
    7272    },
    7373
    74     // FIXME: remove once migrated to SourceFrame2.
    75     addResourceSourceToFrame: function(identifier, element)
    76     {
    77     },
    78 
    79     // FIXME: remove once migrated to SourceFrame2.
    80     addSourceToFrame: function(mimeType, source, element)
    81     {
    82         return false;
    83     },
    84 
    8574    loaded: function()
    8675    {
     
    9988    windowUnloading: function()
    10089    {
     90    },
     91
     92    copyText: function()
     93    {
    10194    }
    10295}
  • trunk/WebCore/inspector/front-end/ResourceView.js

    r53806 r53941  
    132132    },
    133133
     134    show: function(parentElement)
     135    {
     136        WebInspector.View.prototype.show.call(this, parentElement);
     137        this._selectTab();
     138    },
     139
    134140    set headersVisible(x)
    135141    {
     
    137143            return;
    138144        this._headersVisible = x;
    139         if (x) {
     145        if (x)
    140146            this.element.addStyleClass("headers-visible");
    141             this._selectTab();
    142         } else {
     147        else
    143148            this.element.removeStyleClass("headers-visible");
     149        this._selectTab();
     150    },
     151
     152    _selectTab: function()
     153    {
     154        if (this._headersVisible) {
     155            if (WebInspector.settings.resourceViewTab === "headers")
     156                this._selectHeadersTab();
     157            else
     158                this._selectContentTab();
     159        } else
    144160            this._innerSelectContentTab();
    145         }
    146     },
    147 
    148     _selectTab: function()
    149     {
    150         if (WebInspector.settings.resourceViewTab === "headers")
    151             this._selectHeadersTab();
    152         else
    153             this._selectContentTab();
    154161    },
    155162
     
    175182        this.contentElement.removeStyleClass("hidden");
    176183        this.headersElement.addStyleClass("hidden");
     184        if ("resize" in this)
     185            this.resize();
    177186    },
    178187
  • trunk/WebCore/inspector/front-end/ResourcesPanel.js

    r53806 r53941  
    711711WebInspector.ResourcesPanel.prototype.__proto__ = WebInspector.AbstractTimelinePanel.prototype;
    712712
     713WebInspector.getResourceContent = function(identifier, callback)
     714{
     715    InspectorBackend.getResourceContent(WebInspector.Callback.wrap(callback), identifier);
     716}
     717
     718WebInspector.didGetResourceContent = WebInspector.Callback.processCallback;
     719
    713720WebInspector.ResourceTimeCalculator = function(startAtZero)
    714721{
  • trunk/WebCore/inspector/front-end/ScriptView.js

    r51528 r53941  
    3434    this._frameNeedsSetup = true;
    3535    this._sourceFrameSetup = false;
    36 
    37     this.sourceFrame = new WebInspector.SourceFrame(null, this._addBreakpoint.bind(this));
     36    this.sourceFrame = new WebInspector.SourceFrame(this._addBreakpoint.bind(this));
    3837
    3938    this.element.appendChild(this.sourceFrame.element);
     
    4544        WebInspector.View.prototype.show.call(this, parentElement);
    4645        this.setupSourceFrameIfNeeded();
    47     },
    48 
    49     hide: function()
    50     {
    51         WebInspector.View.prototype.hide.call(this);
    52         this._currentSearchResultIndex = -1;
     46        this.resize();
    5347    },
    5448
     
    6054        this.attach();
    6155
    62         if (!InspectorFrontendHost.addSourceToFrame("text/javascript", this.script.source, this.sourceFrame.element))
    63             return;
    64 
     56        this.sourceFrame.setContent("text/javascript", this.script.source);
     57        this._sourceFrameSetup = true;
    6558        delete this._frameNeedsSetup;
    66 
    67         this.sourceFrame.addEventListener("syntax highlighting complete", this._syntaxHighlightingComplete, this);
    68         this.sourceFrame.syntaxHighlightJavascript();
    6959    },
    7060
     
    8474    // generic and work with ScriptView just fine.
    8575
     76    hide: WebInspector.SourceView.prototype.hide,
    8677    revealLine: WebInspector.SourceView.prototype.revealLine,
    8778    highlightLine: WebInspector.SourceView.prototype.highlightLine,
     
    9889    _jumpToSearchResult: WebInspector.SourceView.prototype._jumpToSearchResult,
    9990    _sourceFrameSetupFinished: WebInspector.SourceView.prototype._sourceFrameSetupFinished,
    100     _syntaxHighlightingComplete: WebInspector.SourceView.prototype._syntaxHighlightingComplete
     91    resize: WebInspector.SourceView.prototype.resize
    10192}
    10293
  • trunk/WebCore/inspector/front-end/ScriptsPanel.js

    r53806 r53941  
    800800        this.sidebarResizeElement.style.right = (newWidth - 3) + "px";
    801801
     802        this.resize();
    802803        event.preventDefault();
    803804    },
  • trunk/WebCore/inspector/front-end/SourceFrame.js

    r53794 r53941  
    11/*
    2  * Copyright (C) 2008 Apple Inc. All Rights Reserved.
    3  * Copyright (C) 2009 Joseph Pecoraro
     2 * Copyright (C) 2009 Google Inc. All rights reserved.
    43 *
    54 * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
    10  * 2. Redistributions in binary form must reproduce the above copyright
    11  *    notice, this list of conditions and the following disclaimer in the
    12  *    documentation and/or other materials provided with the distribution.
     5 * modification, are permitted provided that the following conditions are
     6 * met:
    137 *
    14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
    15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
    18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
    22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     8 *     * Redistributions of source code must retain the above copyright
     9 * notice, this list of conditions and the following disclaimer.
     10 *     * Redistributions in binary form must reproduce the above
     11 * copyright notice, this list of conditions and the following disclaimer
     12 * in the documentation and/or other materials provided with the
     13 * distribution.
     14 *     * Neither the name of Google Inc. nor the names of its
     15 * contributors may be used to endorse or promote products derived from
     16 * this software without specific prior written permission.
     17 *
     18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    2327 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    2428 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2529 */
    2630
    27 WebInspector.SourceFrame = function(element, addBreakpointDelegate)
     31WebInspector.SourceFrame = function(addBreakpointDelegate)
    2832{
    29     this.messages = [];
     33    this._editor = new WebInspector.TextEditor(WebInspector.platform);
     34    this._textModel = this._editor.textModel;
     35    this._editor.lineNumberDecorator = new WebInspector.BreakpointLineNumberDecorator(this);
     36    this._editor.lineDecorator = new WebInspector.ExecutionLineDecorator(this);
     37    this._editor.readOnly = true;
     38    this._messages = [];
     39    this._rowMessages = {};
     40    this._messageBubbles = {};
    3041    this.breakpoints = [];
    3142    this._shortcuts = {};
     43    this.element = this._editor.element;
     44    this.element.addEventListener("keydown", this._keyDown.bind(this), true);
     45    this._loaded = false;
    3246
    3347    this.addBreakpointDelegate = addBreakpointDelegate;
    34 
    35     this.element = element || document.createElement("iframe");
    36     this.element.addStyleClass("source-view-frame");
    37     this.element.setAttribute("viewsource", "true");
    38 
    39     this.element.addEventListener("load", this._loaded.bind(this), false);
    4048}
    4149
    4250WebInspector.SourceFrame.prototype = {
     51
    4352    get executionLine()
    4453    {
     
    5059        if (this._executionLine === x)
    5160            return;
    52 
    53         var previousLine = this._executionLine;
    5461        this._executionLine = x;
    55 
    56         this._updateExecutionLine(previousLine);
    57     },
    58 
    59     sourceRow: function(lineNumber)
    60     {
    61         if (!lineNumber || !this.element.contentDocument)
    62             return;
    63 
    64         var table = this.element.contentDocument.getElementsByTagName("table")[0];
    65         if (!table)
    66             return;
    67 
    68         var rows = table.rows;
    69 
    70         // Line numbers are a 1-based index, but the rows collection is 0-based.
    71         --lineNumber;
    72 
    73         return rows[lineNumber];
    74     },
    75 
    76     lineNumberForSourceRow: function(sourceRow)
    77     {
    78         // Line numbers are a 1-based index, but the rows collection is 0-based.
    79         var lineNumber = 0;
    80         while (sourceRow) {
    81             ++lineNumber;
    82             sourceRow = sourceRow.previousSibling;
    83         }
    84 
    85         return lineNumber;
     62        this._editor.repaintAll();
    8663    },
    8764
    8865    revealLine: function(lineNumber)
    8966    {
    90         if (!this._isContentLoaded()) {
     67        if (!this._loaded)
    9168            this._lineNumberToReveal = lineNumber;
    92             return;
    93         }
    94 
    95         var row = this.sourceRow(lineNumber);
    96         if (row)
    97             row.scrollIntoViewIfNeeded(true);
     69        else
     70            this._editor.reveal(lineNumber - 1, 0);
    9871    },
    9972
     
    10174    {
    10275        this.breakpoints.push(breakpoint);
    103         breakpoint.addEventListener("enabled", this._breakpointEnableChanged, this);
    104         breakpoint.addEventListener("disabled", this._breakpointEnableChanged, this);
     76        breakpoint.addEventListener("enabled", this._breakpointChanged, this);
     77        breakpoint.addEventListener("disabled", this._breakpointChanged, this);
     78        breakpoint.addEventListener("condition-changed", this._breakpointChanged, this);
    10579        this._addBreakpointToSource(breakpoint);
    10680    },
     
    11185        breakpoint.removeEventListener("enabled", null, this);
    11286        breakpoint.removeEventListener("disabled", null, this);
     87        breakpoint.removeEventListener("condition-changed", null, this);
    11388        this._removeBreakpointFromSource(breakpoint);
    11489    },
     
    11994        if (!msg.message || msg.line <= 0 || !msg.isErrorOrWarning())
    12095            return;
    121         this.messages.push(msg);
     96        this._messages.push(msg);
    12297        this._addMessageToSource(msg);
    12398    },
     
    125100    clearMessages: function()
    126101    {
    127         this.messages = [];
    128 
    129         if (!this.element.contentDocument)
    130             return;
    131 
    132         var bubbles = this.element.contentDocument.querySelectorAll(".webkit-html-message-bubble");
    133         if (!bubbles)
    134             return;
    135 
    136         for (var i = 0; i < bubbles.length; ++i) {
    137             var bubble = bubbles[i];
     102        for (var line in this._messageBubbles) {
     103            var bubble = this._messageBubbles[line];
    138104            bubble.parentNode.removeChild(bubble);
    139105        }
     106
     107        this._messages = [];
     108        this._rowMessages = {};
     109        this._messageBubbles = {};
     110        this._editor.packAndRepaintAll();
    140111    },
    141112
    142113    sizeToFitContentHeight: function()
    143114    {
    144         if (this.element.contentDocument) {
    145             this.element.style.setProperty("height", this.element.contentDocument.body.offsetHeight + "px");
    146             this.element.contentDocument.body.addStyleClass("webkit-height-sized-to-fit");
    147         }
    148     },
    149 
    150     _highlightLineEnds: function(event)
    151     {
    152         event.target.parentNode.removeStyleClass("webkit-highlighted-line");
    153     },
    154 
    155     highlightLine: function(lineNumber)
    156     {
    157         if (!this._isContentLoaded()) {
    158             this._lineNumberToHighlight = lineNumber;
    159             return;
    160         }
    161 
    162         var sourceRow = this.sourceRow(lineNumber);
    163         if (!sourceRow)
    164             return;
    165         var line = sourceRow.getElementsByClassName('webkit-line-content')[0];
    166         // Trick to reset the animation if the user clicks on the same link
    167         // Using a timeout to avoid coalesced style updates
    168         line.style.setProperty("-webkit-animation-name", "none");
    169         setTimeout(function () {
    170             line.style.removeProperty("-webkit-animation-name");
    171             sourceRow.addStyleClass("webkit-highlighted-line");
    172         }, 0);
    173     },
    174 
    175     _loaded: function()
    176     {
    177         WebInspector.addMainEventListeners(this.element.contentDocument);
    178         this.element.contentDocument.addEventListener("contextmenu", this._documentContextMenu.bind(this), true);
    179         this.element.contentDocument.addEventListener("mousedown", this._documentMouseDown.bind(this), true);
    180         this.element.contentDocument.addEventListener("keydown", this._documentKeyDown.bind(this), true);
    181         this.element.contentDocument.addEventListener("webkitAnimationEnd", this._highlightLineEnds.bind(this), false);
    182 
    183         // Register 'eval' shortcut.
    184         var platformSpecificModifier = WebInspector.isMac() ? WebInspector.KeyboardShortcut.Modifiers.Meta : WebInspector.KeyboardShortcut.Modifiers.Ctrl;
    185         var shortcut = WebInspector.KeyboardShortcut.makeKey(69 /* 'E' */, platformSpecificModifier | WebInspector.KeyboardShortcut.Modifiers.Shift);
    186         this._shortcuts[shortcut] = this._evalSelectionInCallFrame.bind(this);
    187 
    188         var headElement = this.element.contentDocument.head;
    189         if (!headElement) {
    190             headElement = this.element.contentDocument.createElement("head");
    191             this.element.contentDocument.documentElement.insertBefore(headElement, this.element.contentDocument.documentElement.firstChild);
    192         }
    193        
    194         var linkElement = this.element.contentDocument.createElement("link");
    195         linkElement.type = "text/css";
    196         linkElement.rel = "stylesheet";
    197         linkElement.href = "inspectorSyntaxHighlight.css";
    198         headElement.appendChild(linkElement);
    199 
    200         var styleElement = this.element.contentDocument.createElement("style");
    201         headElement.appendChild(styleElement);
    202 
    203         // Add these style rules here since they are specific to the Inspector. They also behave oddly and not
    204         // all properties apply if added to view-source.css (because it is a user agent sheet.)
    205         var styleText = ".webkit-line-number { background-repeat: no-repeat; background-position: right 1px; }\n";
    206         styleText += ".webkit-execution-line .webkit-line-number { color: transparent; background-image: -webkit-canvas(program-counter); }\n";
    207 
    208         styleText += ".webkit-breakpoint .webkit-line-number { color: white; background-image: -webkit-canvas(breakpoint); }\n";
    209         styleText += ".webkit-breakpoint-disabled .webkit-line-number { color: white; background-image: -webkit-canvas(breakpoint-disabled); }\n";
    210         styleText += ".webkit-breakpoint.webkit-execution-line .webkit-line-number { color: transparent; background-image: -webkit-canvas(breakpoint-program-counter); }\n";
    211         styleText += ".webkit-breakpoint-disabled.webkit-execution-line .webkit-line-number { color: transparent; background-image: -webkit-canvas(breakpoint-disabled-program-counter); }\n";
    212 
    213         styleText += ".webkit-breakpoint.webkit-breakpoint-conditional .webkit-line-number { color: white; background-image: -webkit-canvas(breakpoint-conditional); }\n";
    214         styleText += ".webkit-breakpoint-disabled.webkit-breakpoint-conditional .webkit-line-number { color: white; background-image: -webkit-canvas(breakpoint-disabled-conditional); }\n";
    215         styleText += ".webkit-breakpoint.webkit-breakpoint-conditional.webkit-execution-line .webkit-line-number { color: transparent; background-image: -webkit-canvas(breakpoint-conditional-program-counter); }\n";
    216         styleText += ".webkit-breakpoint-disabled.webkit-breakpoint-conditional.webkit-execution-line .webkit-line-number { color: transparent; background-image: -webkit-canvas(breakpoint-disabled-conditional-program-counter); }\n";
    217 
    218         styleText += ".webkit-execution-line .webkit-line-content { background-color: rgb(171, 191, 254); outline: 1px solid rgb(64, 115, 244); }\n";
    219         styleText += ".webkit-height-sized-to-fit { overflow-y: hidden }\n";
    220         styleText += ".webkit-line-content { background-color: white; }\n";
    221         styleText += "@-webkit-keyframes fadeout {from {background-color: rgb(255, 255, 120);} to { background-color: white;}}\n";
    222         styleText += ".webkit-highlighted-line .webkit-line-content { background-color: rgb(255, 255, 120); -webkit-animation: 'fadeout' 2s 500ms}\n";
    223 
    224         // TODO: Move these styles into inspector.css once https://bugs.webkit.org/show_bug.cgi?id=28913 is fixed and popup moved into the top frame.
    225         styleText += ".popup-content { position: absolute; z-index: 10000; padding: 4px; background-color: rgb(203, 226, 255); -webkit-border-radius: 7px; border: 2px solid rgb(169, 172, 203); }";
    226         styleText += ".popup-glasspane { position: absolute; top: 0; left: 0; height: 100%; width: 100%; opacity: 0; z-index: 9900; }";
    227         styleText += ".popup-message { background-color: transparent; font-family: Lucida Grande, sans-serif; font-weight: normal; font-size: 11px; text-align: left; text-shadow: none; color: rgb(85, 85, 85); cursor: default; margin: 0 0 2px 0; }";
    228         styleText += ".popup-content.breakpoint-condition { width: 90%; }";
    229         styleText += ".popup-content input#bp-condition { font-family: monospace; margin: 0; border: 1px inset rgb(190, 190, 190) !important; width: 100%; box-shadow: none !important; outline: none !important; -webkit-user-modify: read-write; }";
    230         // This class is already in inspector.css
    231         styleText += ".hidden { display: none !important; }";
    232 
    233         styleElement.textContent = styleText;
    234 
    235         this._needsProgramCounterImage = true;
    236         this._needsBreakpointImages = true;
    237 
    238         this.element.contentWindow.Element.prototype.addStyleClass = Element.prototype.addStyleClass;
    239         this.element.contentWindow.Element.prototype.removeStyleClass = Element.prototype.removeStyleClass;
    240         this.element.contentWindow.Element.prototype.removeChildren = Element.prototype.removeChildren;
    241         this.element.contentWindow.Element.prototype.positionAt = Element.prototype.positionAt;
    242         this.element.contentWindow.Element.prototype.removeMatchingStyleClasses = Element.prototype.removeMatchingStyleClasses;
    243         this.element.contentWindow.Element.prototype.hasStyleClass = Element.prototype.hasStyleClass;
    244         this.element.contentWindow.Element.prototype.pageOffsetRelativeToWindow = Element.prototype.pageOffsetRelativeToWindow;
    245         this.element.contentWindow.Element.prototype.__defineGetter__("totalOffsetLeft", Element.prototype.__lookupGetter__("totalOffsetLeft"));
    246         this.element.contentWindow.Element.prototype.__defineGetter__("totalOffsetTop", Element.prototype.__lookupGetter__("totalOffsetTop"));
    247         this.element.contentWindow.Node.prototype.enclosingNodeOrSelfWithNodeName = Node.prototype.enclosingNodeOrSelfWithNodeName;
    248         this.element.contentWindow.Node.prototype.enclosingNodeOrSelfWithNodeNameInArray = Node.prototype.enclosingNodeOrSelfWithNodeNameInArray;
     115        this._editor.packAndRepaintAll();
     116    },
     117
     118    setContent: function(mimeType, content)
     119    {
     120        this._loaded = true;
     121        this._editor.mimeType = mimeType;
     122        this._editor.text = content;
    249123
    250124        this._addExistingMessagesToSource();
    251125        this._addExistingBreakpointsToSource();
    252         this._updateExecutionLine();
    253126        if (this._executionLine)
    254127            this.revealLine(this._executionLine);
     
    258131            delete this._lineNumberToReveal;
    259132        }
    260 
    261         if (this._lineNumberToHighlight) {
    262             this.highlightLine(this._lineNumberToHighlight);
    263             delete this._lineNumberToHighlight;
    264         }
    265 
    266         this.dispatchEventToListeners("content loaded");
    267     },
    268 
    269     _isContentLoaded: function() {
    270         var doc = this.element.contentDocument;
    271         return doc && doc.getElementsByTagName("table")[0];
    272     },
    273 
    274     _documentContextMenu: function(event)
    275     {
    276         if (!event.target.hasStyleClass("webkit-line-number"))
    277             return;
    278         if (!this.addBreakpointDelegate)
    279             return;
    280 
    281         var sourceRow = event.target.enclosingNodeOrSelfWithNodeName("tr");
    282         var contextMenu = new WebInspector.ContextMenu();
    283        
    284         if (!sourceRow._breakpointObject && this.addBreakpointDelegate) {
    285             var lineNumber = this.lineNumberForSourceRow(sourceRow);
    286             // This row doesn't have a breakpoint: We want to show Add Breakpoint and Add and Edit Breakpoint.
    287             contextMenu.appendItem(WebInspector.UIString("Add Breakpoint"), this.addBreakpointDelegate.bind(this, lineNumber));
    288 
    289             function addConditionalBreakpoint()
    290             {
    291                 this.addBreakpointDelegate(lineNumber);
    292                 var breakpoint = sourceRow._breakpointObject;
    293                 if (breakpoint)
    294                     this._editBreakpointCondition(event.target, sourceRow, breakpoint);
    295             }
    296 
    297             contextMenu.appendItem(WebInspector.UIString("Add Conditional Breakpoint..."), addConditionalBreakpoint.bind(this));
    298         } else if (sourceRow._breakpointObject) {
    299             // This row has a breakpoint, we want to show edit and remove breakpoint, and either disable or enable.
    300             contextMenu.appendItem(WebInspector.UIString("Remove Breakpoint"), WebInspector.panels.scripts.removeBreakpoint.bind(WebInspector.panels.scripts, sourceRow._breakpointObject));
    301             contextMenu.appendItem(WebInspector.UIString("Edit Breakpoint..."), this._editBreakpointCondition.bind(this, event.target, sourceRow, sourceRow._breakpointObject));
    302             if (sourceRow._breakpointObject.enabled)
    303                 contextMenu.appendItem(WebInspector.UIString("Disable Breakpoint"), function() { sourceRow._breakpointObject.enabled = false; });
    304             else
    305                 contextMenu.appendItem(WebInspector.UIString("Enable Breakpoint"), function() { sourceRow._breakpointObject.enabled = true; });
    306         }
    307        
    308         contextMenu.show(event);
    309     },
    310 
    311     _documentMouseDown: function(event)
    312     {
    313         if (!event.target.hasStyleClass("webkit-line-number"))
    314             return;
    315         if (event.button != 0 || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey)
    316             return;
    317         var sourceRow = event.target.enclosingNodeOrSelfWithNodeName("tr");
    318         if (sourceRow._breakpointObject)
    319             WebInspector.panels.scripts.removeBreakpoint(sourceRow._breakpointObject);
    320         else if (this.addBreakpointDelegate)
    321             this.addBreakpointDelegate(this.lineNumberForSourceRow(sourceRow));
    322 
    323         event.preventDefault();
    324     },
    325 
    326     _editBreakpointCondition: function(eventTarget, sourceRow, breakpoint)
    327     {
    328         // TODO: Migrate the popup to the top-level document and remove the blur listener from conditionElement once https://bugs.webkit.org/show_bug.cgi?id=28913 is fixed.
    329         var popupDocument = this.element.contentDocument;
    330         this._showBreakpointConditionPopup(eventTarget, breakpoint.line, popupDocument);
    331 
    332         function committed(element, newText)
    333         {
    334             breakpoint.condition = newText;
    335             if (breakpoint.condition)
    336                 sourceRow.addStyleClass("webkit-breakpoint-conditional");
    337             else
    338                 sourceRow.removeStyleClass("webkit-breakpoint-conditional");
    339             dismissed.call(this);
    340         }
    341 
    342         function dismissed()
    343         {
    344             this._popup.hide();
    345             delete this._conditionEditorElement;
    346         }
    347 
    348         var dismissedHandler = dismissed.bind(this);
    349         this._conditionEditorElement.addEventListener("blur", dismissedHandler, false);
    350 
    351         WebInspector.startEditing(this._conditionEditorElement, committed.bind(this), dismissedHandler);
    352         this._conditionEditorElement.value = breakpoint.condition;
    353         this._conditionEditorElement.select();
    354     },
    355 
    356     _showBreakpointConditionPopup: function(clickedElement, lineNumber, popupDocument)
    357     {
    358         var popupContentElement = this._createPopupElement(lineNumber, popupDocument);
    359         var lineElement = clickedElement.enclosingNodeOrSelfWithNodeName("td").nextSibling;
    360         if (this._popup) {
    361             this._popup.hide();
    362             this._popup.element = popupContentElement;
    363         } else {
    364             this._popup = new WebInspector.Popup(popupContentElement);
    365             this._popup.autoHide = true;
    366         }
    367         this._popup.anchor = lineElement;
    368         this._popup.show();
    369     },
    370 
    371     _createPopupElement: function(lineNumber, popupDocument)
    372     {
    373         var popupContentElement = popupDocument.createElement("div");
    374         popupContentElement.className = "popup-content breakpoint-condition";
    375 
    376         var labelElement = document.createElement("label");
    377         labelElement.className = "popup-message";
    378         labelElement.htmlFor = "bp-condition";
    379         labelElement.appendChild(document.createTextNode(WebInspector.UIString("The breakpoint on line %d will stop only if this expression is true:", lineNumber)));
    380         popupContentElement.appendChild(labelElement);
    381 
    382         var editorElement = document.createElement("input");
    383         editorElement.id = "bp-condition";
    384         editorElement.type = "text"
    385         popupContentElement.appendChild(editorElement);
    386         this._conditionEditorElement = editorElement;
    387 
    388         return popupContentElement;
    389     },
    390 
    391     _documentKeyDown: function(event)
    392     {
    393         var shortcut = WebInspector.KeyboardShortcut.makeKeyFromEvent(event);
    394         var handler = this._shortcuts[shortcut];
    395         if (handler) {
    396             handler(event);
    397             event.preventDefault();
    398         } else {
    399             WebInspector.documentKeyDown(event);
    400         }
    401     },
    402 
    403     _evalSelectionInCallFrame: function(event)
    404     {
    405         if (!WebInspector.panels.scripts || !WebInspector.panels.scripts.paused)
    406             return;
    407 
    408         var selection = this.element.contentWindow.getSelection();
    409         if (!selection.rangeCount)
    410             return;
    411 
    412         var expression = selection.getRangeAt(0).toString().trim();
    413         WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression, false, "console", function(result, exception) {
    414             WebInspector.showConsole();
    415             var commandMessage = new WebInspector.ConsoleCommand(expression);
    416             WebInspector.console.addMessage(commandMessage);
    417             WebInspector.console.addMessage(new WebInspector.ConsoleCommandResult(result, exception, commandMessage));
    418         });
    419     },
    420 
    421     _breakpointEnableChanged: function(event)
    422     {
    423         var breakpoint = event.target;
    424         var sourceRow = this.sourceRow(breakpoint.line);
    425         if (!sourceRow)
    426             return;
    427 
    428         sourceRow.addStyleClass("webkit-breakpoint");
    429 
    430         if (breakpoint.enabled)
    431             sourceRow.removeStyleClass("webkit-breakpoint-disabled");
    432         else
    433             sourceRow.addStyleClass("webkit-breakpoint-disabled");
    434     },
    435 
    436     _updateExecutionLine: function(previousLine)
    437     {
    438         if (previousLine) {
    439             var sourceRow = this.sourceRow(previousLine);
    440             if (sourceRow)
    441                 sourceRow.removeStyleClass("webkit-execution-line");
    442         }
    443 
    444         if (!this._executionLine)
    445             return;
    446 
    447         this._drawProgramCounterImageIfNeeded();
    448 
    449         var sourceRow = this.sourceRow(this._executionLine);
    450         if (sourceRow)
    451             sourceRow.addStyleClass("webkit-execution-line");
    452     },
    453 
    454     _addExistingBreakpointsToSource: function()
    455     {
    456         var length = this.breakpoints.length;
    457         for (var i = 0; i < length; ++i)
    458             this._addBreakpointToSource(this.breakpoints[i]);
    459     },
    460 
    461     _addBreakpointToSource: function(breakpoint)
    462     {
    463         var sourceRow = this.sourceRow(breakpoint.line);
    464         if (!sourceRow)
    465             return;
    466 
    467         breakpoint.sourceText = sourceRow.getElementsByClassName('webkit-line-content')[0].textContent;
    468 
    469         this._drawBreakpointImagesIfNeeded();
    470 
    471         sourceRow._breakpointObject = breakpoint;
    472 
    473         sourceRow.addStyleClass("webkit-breakpoint");
    474         if (!breakpoint.enabled)
    475             sourceRow.addStyleClass("webkit-breakpoint-disabled");
    476         if (breakpoint.condition)
    477             sourceRow.addStyleClass("webkit-breakpoint-conditional");
    478     },
    479 
    480     _removeBreakpointFromSource: function(breakpoint)
    481     {
    482         var sourceRow = this.sourceRow(breakpoint.line);
    483         if (!sourceRow)
    484             return;
    485 
    486         delete sourceRow._breakpointObject;
    487 
    488         sourceRow.removeStyleClass("webkit-breakpoint");
    489         sourceRow.removeStyleClass("webkit-breakpoint-disabled");
    490         sourceRow.removeStyleClass("webkit-breakpoint-conditional");
     133        this._editor.setCoalescingUpdate(true);
     134        this._editor.updateCanvasSize();
     135        this._editor.packAndRepaintAll();
     136        this._editor.setCoalescingUpdate(false);
     137    },
     138
     139    findSearchMatches: function(query)
     140    {
     141        var ranges = [];
     142
     143        // First do case-insensitive search.
     144        var regex = "";
     145        for (var i = 0; i < query.length; ++i) {
     146            var char = query.charAt(i);
     147            if (char === "]")
     148                char = "\\]";
     149            regex += "[" + char + "]";
     150        }
     151        var regexObject = new RegExp(regex, "i");
     152        this._collectRegexMatches(regexObject, ranges);
     153
     154        // Then try regex search if user knows the / / hint.
     155        try {
     156            if (/^\/.*\/$/.test(query))
     157                this._collectRegexMatches(new RegExp(query.substring(1, query.length - 1)), ranges);
     158        } catch (e) {
     159            // Silent catch.
     160        }
     161        return ranges;
     162    },
     163
     164    _collectRegexMatches: function(regexObject, ranges)
     165    {
     166        for (var i = 0; i < this._textModel.linesCount; ++i) {
     167            var line = this._textModel.line(i);
     168            var offset = 0;
     169            do {
     170                var match = regexObject.exec(line);
     171                if (match) {
     172                    ranges.push(new WebInspector.TextRange(i, offset + match.index, i, offset + match.index + match[0].length));
     173                    offset += match.index + 1;
     174                    line = line.substring(match.index + 1);
     175                }
     176            } while (match)
     177        }
     178        return ranges;
     179    },
     180
     181    setSelection: function(range)
     182    {
     183        this._editor.setSelection(range.startLine, range.startColumn, range.endLine, range.endColumn);
     184    },
     185
     186    clearSelection: function()
     187    {
     188        var range = this._editor.selection;
     189        this._editor.setSelection(range.endLine, range.endColumn, range.endLine, range.endColumn);
    491190    },
    492191
     
    508207    _addExistingMessagesToSource: function()
    509208    {
    510         var length = this.messages.length;
     209        var length = this._messages.length;
    511210        for (var i = 0; i < length; ++i)
    512             this._addMessageToSource(this.messages[i]);
     211            this._addMessageToSource(this._messages[i]);
    513212    },
    514213
    515214    _addMessageToSource: function(msg)
    516215    {
    517         var row = this.sourceRow(msg.line);
    518         if (!row)
    519             return;
    520 
    521         var cell = row.cells[1];
    522         if (!cell)
    523             return;
    524 
    525         var messageBubbleElement = cell.lastChild;
     216        if (msg.line >= this._textModel.linesCount)
     217            return;
     218
     219        var messageBubbleElement = this._messageBubbles[msg.line];
    526220        if (!messageBubbleElement || messageBubbleElement.nodeType !== Node.ELEMENT_NODE || !messageBubbleElement.hasStyleClass("webkit-html-message-bubble")) {
    527             messageBubbleElement = this.element.contentDocument.createElement("div");
     221            messageBubbleElement = document.createElement("div");
    528222            messageBubbleElement.className = "webkit-html-message-bubble";
    529             cell.appendChild(messageBubbleElement);
    530         }
    531 
    532         if (!row.messages)
    533             row.messages = [];
    534 
    535         for (var i = 0; i < row.messages.length; ++i) {
    536             if (row.messages[i].isEqual(msg, true)) {
    537                 this._incrementMessageRepeatCount(row.messages[i], msg.repeatDelta);
     223            this._messageBubbles[msg.line] = messageBubbleElement;
     224            this._editor.setDivDecoration(msg.line - 1, messageBubbleElement);
     225        }
     226
     227        var rowMessages = this._rowMessages[msg.line];
     228        if (!rowMessages) {
     229            rowMessages = [];
     230            this._rowMessages[msg.line] = rowMessages;
     231        }
     232
     233        for (var i = 0; i < rowMessages.length; ++i) {
     234            if (rowMessages[i].isEqual(msg, true)) {
     235                this._incrementMessageRepeatCount(rowMessages[i], msg.repeatDelta);
     236                this._editor.packAndRepaintAll();
    538237                return;
    539238            }
    540239        }
    541240
    542         row.messages.push(msg);
     241        rowMessages.push(msg);
    543242
    544243        var imageURL;
     
    554253        }
    555254
    556         var messageLineElement = this.element.contentDocument.createElement("div");
     255        var messageLineElement = document.createElement("div");
    557256        messageLineElement.className = "webkit-html-message-line";
    558257        messageBubbleElement.appendChild(messageLineElement);
     
    562261        image.src = imageURL;
    563262        image.className = "webkit-html-message-icon";
    564 
    565         // Adopt the image element since it wasn't created in element's contentDocument.
    566         image = this.element.contentDocument.adoptNode(image);
    567263        messageLineElement.appendChild(image);
    568         messageLineElement.appendChild(this.element.contentDocument.createTextNode(msg.message));
     264        messageLineElement.appendChild(document.createTextNode(msg.message));
    569265
    570266        msg._resourceMessageLineElement = messageLineElement;
    571     },
    572 
    573     _drawProgramCounterInContext: function(ctx, glow)
    574     {
    575         if (glow)
     267
     268        this._editor.packAndRepaintAll();
     269    },
     270
     271    _addExistingBreakpointsToSource: function()
     272    {
     273        var length = this.breakpoints.length;
     274        for (var i = 0; i < length; ++i)
     275            this._addBreakpointToSource(this.breakpoints[i]);
     276    },
     277
     278    _addBreakpointToSource: function(breakpoint)
     279    {
     280        this._textModel.setAttribute(breakpoint.line - 1, "breakpoint", breakpoint);
     281        this._editor.paintLineNumbers();
     282    },
     283
     284    _removeBreakpointFromSource: function(breakpoint)
     285    {
     286        this._textModel.removeAttribute(breakpoint.line - 1, "breakpoint");
     287        this._editor.paintLineNumbers();
     288    },
     289
     290    _contextMenu: function(lineNumber, event)
     291    {
     292        if (!this.addBreakpointDelegate)
     293            return;
     294
     295        var contextMenu = new WebInspector.ContextMenu();
     296
     297        var breakpoint = this._textModel.getAttribute(lineNumber, "breakpoint");
     298        if (!breakpoint) {
     299            // This row doesn't have a breakpoint: We want to show Add Breakpoint and Add and Edit Breakpoint.
     300            contextMenu.appendItem(WebInspector.UIString("Add Breakpoint"), this.addBreakpointDelegate.bind(this, lineNumber + 1));
     301
     302            function addConditionalBreakpoint()
     303            {
     304                this.addBreakpointDelegate(lineNumber + 1);
     305                var breakpoint = this._textModel.getAttribute(lineNumber, "breakpoint");
     306                if (breakpoint)
     307                    this._editBreakpointCondition(breakpoint);
     308            }
     309
     310            contextMenu.appendItem(WebInspector.UIString("Add Conditional Breakpoint..."), addConditionalBreakpoint.bind(this));
     311        } else {
     312            // This row has a breakpoint, we want to show edit and remove breakpoint, and either disable or enable.
     313            contextMenu.appendItem(WebInspector.UIString("Remove Breakpoint"), WebInspector.panels.scripts.removeBreakpoint.bind(WebInspector.panels.scripts, breakpoint));
     314            contextMenu.appendItem(WebInspector.UIString("Edit Breakpoint..."), this._editBreakpointCondition.bind(this, breakpoint));
     315            if (breakpoint.enabled)
     316                contextMenu.appendItem(WebInspector.UIString("Disable Breakpoint"), function() { breakpoint.enabled = false; });
     317            else
     318                contextMenu.appendItem(WebInspector.UIString("Enable Breakpoint"), function() { breakpoint.enabled = true; });
     319        }
     320        contextMenu.show(event);
     321    },
     322
     323    _toggleBreakpoint: function(lineNumber, event)
     324    {
     325        if (event.button != 0 || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey)
     326            return;
     327        var breakpoint = this._textModel.getAttribute(lineNumber, "breakpoint");
     328        if (breakpoint)
     329            WebInspector.panels.scripts.removeBreakpoint(breakpoint);
     330        else if (this.addBreakpointDelegate)
     331            this.addBreakpointDelegate(lineNumber + 1);
     332        event.preventDefault();
     333    },
     334
     335    _editBreakpointCondition: function(breakpoint)
     336    {
     337        this._showBreakpointConditionPopup(breakpoint.line);
     338
     339        function committed(element, newText)
     340        {
     341            breakpoint.condition = newText;
     342            this._editor.paintLineNumbers();
     343            dismissed.call(this);
     344        }
     345
     346        function dismissed()
     347        {
     348            this._editor.setDivDecoration(breakpoint.line - 1, null);
     349            delete this._conditionEditorElement;
     350        }
     351
     352        var dismissedHandler = dismissed.bind(this);
     353        this._conditionEditorElement.addEventListener("blur", dismissedHandler, false);
     354
     355        WebInspector.startEditing(this._conditionEditorElement, committed.bind(this), dismissedHandler);
     356        this._conditionEditorElement.value = breakpoint.condition;
     357        this._conditionEditorElement.select();
     358    },
     359
     360    _showBreakpointConditionPopup: function(lineNumber)
     361    {
     362        var conditionElement = this._createConditionElement(lineNumber);
     363        this._editor.setDivDecoration(lineNumber - 1, conditionElement);
     364    },
     365
     366    _createConditionElement: function(lineNumber)
     367    {
     368        var conditionElement = document.createElement("div");
     369        conditionElement.className = "source-breakpoint-condition";
     370
     371        var labelElement = document.createElement("label");
     372        labelElement.className = "source-breakpoint-message";
     373        labelElement.htmlFor = "source-breakpoint-condition";
     374        labelElement.appendChild(document.createTextNode(WebInspector.UIString("The breakpoint on line %d will stop only if this expression is true:", lineNumber)));
     375        conditionElement.appendChild(labelElement);
     376
     377        var editorElement = document.createElement("input");
     378        editorElement.id = "source-breakpoint-condition";
     379        editorElement.type = "text"
     380        conditionElement.appendChild(editorElement);
     381        this._conditionEditorElement = editorElement;
     382
     383        return conditionElement;
     384    },
     385
     386    _keyDown: function(event)
     387    {
     388        var shortcut = WebInspector.KeyboardShortcut.makeKeyFromEvent(event);
     389        var handler = this._shortcuts[shortcut];
     390        if (handler) {
     391            handler(event);
     392            event.preventDefault();
     393        } else {
     394            WebInspector.documentKeyDown(event);
     395        }
     396    },
     397
     398    _evalSelectionInCallFrame: function(event)
     399    {
     400        if (!WebInspector.panels.scripts || !WebInspector.panels.scripts.paused)
     401            return;
     402
     403        var selection = this.element.contentWindow.getSelection();
     404        if (!selection.rangeCount)
     405            return;
     406
     407        var expression = selection.getRangeAt(0).toString().trimWhitespace();
     408        WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression, false, "console", function(result, exception) {
     409            WebInspector.showConsole();
     410            var commandMessage = new WebInspector.ConsoleCommand(expression);
     411            WebInspector.console.addMessage(commandMessage);
     412            WebInspector.console.addMessage(new WebInspector.ConsoleCommandResult(result, exception, commandMessage));
     413        });
     414    },
     415
     416    _breakpointChanged: function(event)
     417    {
     418        this._editor.paintLineNumbers();
     419    },
     420
     421    resize: function()
     422    {
     423        this._editor.updateCanvasSize();
     424    }
     425}
     426
     427WebInspector.SourceFrame.prototype.__proto__ = WebInspector.Object.prototype;
     428
     429WebInspector.BreakpointLineNumberDecorator = function(sourceFrame)
     430{
     431    this._sourceFrame = sourceFrame;
     432    this._textModel = sourceFrame._editor.textModel;
     433}
     434
     435WebInspector.BreakpointLineNumberDecorator.prototype = {
     436    decorate: function(lineNumber, ctx, x, y, width, height, lineHeight)
     437    {
     438        var breakpoint = this._textModel.getAttribute(lineNumber, "breakpoint");
     439        var isExecutionLine = lineNumber + 1 === this._sourceFrame._executionLine;
     440        if (breakpoint || isExecutionLine) {
    576441            ctx.save();
    577 
     442            ctx.translate(x + 4, y + 2);
     443            var breakpointWidth = width - 6;
     444            var breakpointHeight = lineHeight - 4;
     445   
     446            if (breakpoint)
     447                this._paintBreakpoint(ctx, breakpointWidth, breakpointHeight, breakpoint);
     448   
     449            if (isExecutionLine)
     450                this._paintProgramCounter(ctx, breakpointWidth, breakpointHeight, false);
     451
     452            ctx.restore();
     453        }
     454
     455        if (isExecutionLine) {
     456            // Override default behavior.
     457            return true;
     458        }
     459
     460        ctx.fillStyle = breakpoint ? "rgb(255,255,255)" : "rgb(155,155,155)";
     461        return false;
     462    },
     463
     464    _paintBreakpoint: function(ctx, width, height, breakpoint)
     465    {
    578466        ctx.beginPath();
    579         ctx.moveTo(17, 2);
    580         ctx.lineTo(19, 2);
    581         ctx.lineTo(19, 0);
    582         ctx.lineTo(21, 0);
    583         ctx.lineTo(26, 5.5);
    584         ctx.lineTo(21, 11);
    585         ctx.lineTo(19, 11);
    586         ctx.lineTo(19, 9);
    587         ctx.lineTo(17, 9);
     467        ctx.moveTo(0, 2);
     468        ctx.lineTo(2, 0);
     469        ctx.lineTo(width - 5, 0);
     470        ctx.lineTo(width, height / 2);
     471        ctx.lineTo(width - 5, height);
     472        ctx.lineTo(2, height);
     473        ctx.lineTo(0, height - 2);
    588474        ctx.closePath();
    589         ctx.fillStyle = "rgb(142, 5, 4)";
    590 
    591         if (glow) {
    592             ctx.shadowBlur = 4;
    593             ctx.shadowColor = "rgb(255, 255, 255)";
    594             ctx.shadowOffsetX = -1;
    595             ctx.shadowOffsetY = 0;
    596         }
    597 
     475        ctx.fillStyle = breakpoint.condition ? "rgb(217, 142, 1)" : "rgb(1, 142, 217)";
     476        ctx.strokeStyle = breakpoint.condition ? "rgb(205, 103, 0)" : "rgb(0, 103, 205)";
     477        ctx.lineWidth = 3;
    598478        ctx.fill();
    599         ctx.fill(); // Fill twice to get a good shadow and darker anti-aliased pixels.
    600 
    601         if (glow)
    602             ctx.restore();
    603     },
    604 
    605     _drawProgramCounterImageIfNeeded: function()
    606     {
    607         if (!this._needsProgramCounterImage || !this.element.contentDocument)
    608             return;
    609 
    610         var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "program-counter", 26, 11);
    611         ctx.clearRect(0, 0, 26, 11);
    612         this._drawProgramCounterInContext(ctx, true);
    613 
    614         delete this._needsProgramCounterImage;
    615     },
    616 
    617     _drawBreakpointImagesIfNeeded: function(conditional)
    618     {
    619         if (!this._needsBreakpointImages || !this.element.contentDocument)
    620             return;
    621 
    622         function drawBreakpoint(ctx, disabled, conditional)
    623         {
    624             ctx.beginPath();
    625             ctx.moveTo(0, 2);
    626             ctx.lineTo(2, 0);
    627             ctx.lineTo(21, 0);
    628             ctx.lineTo(26, 5.5);
    629             ctx.lineTo(21, 11);
    630             ctx.lineTo(2, 11);
    631             ctx.lineTo(0, 9);
    632             ctx.closePath();
    633             ctx.fillStyle = conditional ? "rgb(217, 142, 1)" : "rgb(1, 142, 217)";
    634             ctx.strokeStyle = conditional ? "rgb(205, 103, 0)" : "rgb(0, 103, 205)";
    635             ctx.lineWidth = 3;
    636             ctx.fill();
    637             ctx.save();
    638             ctx.clip();
    639             ctx.stroke();
    640             ctx.restore();
    641 
    642             if (!disabled)
    643                 return;
    644 
     479
     480        ctx.save();
     481        ctx.clip();
     482        ctx.stroke();
     483        ctx.restore();
     484
     485        if (!breakpoint.enabled) {
    645486            ctx.save();
    646487            ctx.globalCompositeOperation = "destination-out";
    647488            ctx.fillStyle = "rgba(0, 0, 0, 0.5)";
    648             ctx.fillRect(0, 0, 26, 11);
     489            ctx.fillRect(0, 0, width, height);
    649490            ctx.restore();
    650491        }
    651 
    652 
    653         // Unconditional breakpoints.
    654 
    655         var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakpoint", 26, 11);
    656         ctx.clearRect(0, 0, 26, 11);
    657         drawBreakpoint(ctx);
    658 
    659         var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakpoint-program-counter", 26, 11);
    660         ctx.clearRect(0, 0, 26, 11);
    661         drawBreakpoint(ctx);
    662         ctx.clearRect(20, 0, 6, 11);
    663         this._drawProgramCounterInContext(ctx, true);
    664 
    665         var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakpoint-disabled", 26, 11);
    666         ctx.clearRect(0, 0, 26, 11);
    667         drawBreakpoint(ctx, true);
    668 
    669         var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakpoint-disabled-program-counter", 26, 11);
    670         ctx.clearRect(0, 0, 26, 11);
    671         drawBreakpoint(ctx, true);
    672         ctx.clearRect(20, 0, 6, 11);
    673         this._drawProgramCounterInContext(ctx, true);
    674 
    675 
    676         // Conditional breakpoints.
    677 
    678         var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakpoint-conditional", 26, 11);
    679         ctx.clearRect(0, 0, 26, 11);
    680         drawBreakpoint(ctx, false, true);
    681 
    682         var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakpoint-conditional-program-counter", 26, 11);
    683         ctx.clearRect(0, 0, 26, 11);
    684         drawBreakpoint(ctx, false, true);
    685         ctx.clearRect(20, 0, 6, 11);
    686         this._drawProgramCounterInContext(ctx, true);
    687 
    688         var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakpoint-disabled-conditional", 26, 11);
    689         ctx.clearRect(0, 0, 26, 11);
    690         drawBreakpoint(ctx, true, true);
    691 
    692         var ctx = this.element.contentDocument.getCSSCanvasContext("2d", "breakpoint-disabled-conditional-program-counter", 26, 11);
    693         ctx.clearRect(0, 0, 26, 11);
    694         drawBreakpoint(ctx, true, true);
    695         ctx.clearRect(20, 0, 6, 11);
    696         this._drawProgramCounterInContext(ctx, true);
    697 
    698         delete this._needsBreakpointImages;
    699     },
    700 
    701     syntaxHighlightJavascript: function()
    702     {
    703         var table = this.element.contentDocument.getElementsByTagName("table")[0];
    704         if (!table)
    705             return;
    706 
    707         var jsSyntaxHighlighter = new WebInspector.JavaScriptSourceSyntaxHighlighter(table, this);
    708         jsSyntaxHighlighter.process();
    709     },
    710 
    711     syntaxHighlightCSS: function()
    712     {
    713         var table = this.element.contentDocument.getElementsByTagName("table")[0];
    714         if (!table)
    715             return;
    716 
    717         var cssSyntaxHighlighter = new WebInspector.CSSSourceSyntaxHighlighter(table, this);
    718         cssSyntaxHighlighter.process();
     492    },
     493
     494    _paintProgramCounter: function(ctx, width, height)
     495    {
     496        ctx.save();
     497
     498        ctx.beginPath();
     499        ctx.moveTo(width - 9, 2);
     500        ctx.lineTo(width - 7, 2);
     501        ctx.lineTo(width - 7, 0);
     502        ctx.lineTo(width - 5, 0);
     503        ctx.lineTo(width, height / 2);
     504        ctx.lineTo(width - 5, height);
     505        ctx.lineTo(width - 7, height);
     506        ctx.lineTo(width - 7, height - 2);
     507        ctx.lineTo(width - 9, height - 2);
     508        ctx.closePath();
     509        ctx.fillStyle = "rgb(142, 5, 4)";
     510
     511        ctx.shadowBlur = 4;
     512        ctx.shadowColor = "rgb(255, 255, 255)";
     513        ctx.shadowOffsetX = -1;
     514        ctx.shadowOffsetY = 0;
     515
     516        ctx.fill();
     517        ctx.fill(); // Fill twice to get a good shadow and darker anti-aliased pixels.
     518
     519        ctx.restore();
     520    },
     521
     522    mouseDown: function(lineNumber, e)
     523    {
     524        this._sourceFrame._toggleBreakpoint(lineNumber, e);
     525        return true;
     526    },
     527
     528    contextMenu: function(lineNumber, e)
     529    {
     530        this._sourceFrame._contextMenu(lineNumber, e);
     531        return true;
    719532    }
    720533}
    721534
    722 WebInspector.SourceFrame.prototype.__proto__ = WebInspector.Object.prototype;
     535WebInspector.ExecutionLineDecorator = function(sourceFrame)
     536{
     537    this._sourceFrame = sourceFrame;
     538}
     539
     540WebInspector.ExecutionLineDecorator.prototype = {
     541    decorate: function(lineNumber, ctx, x, y, width, height, lineHeight)
     542    {
     543        if (this._sourceFrame._executionLine !== lineNumber + 1)
     544            return;
     545        ctx.save();
     546        ctx.fillStyle = "rgb(171, 191, 254)";
     547        ctx.fillRect(x, y, width, height);
     548       
     549        ctx.beginPath();
     550        ctx.rect(x - 1, y, width + 2, height);
     551        ctx.clip();
     552        ctx.strokeStyle = "rgb(64, 115, 244)";
     553        ctx.stroke();
     554
     555        ctx.restore();
     556    }
     557}
  • trunk/WebCore/inspector/front-end/SourceView.js

    r53794 r53941  
    3131    WebInspector.ResourceView.call(this, resource);
    3232
    33     this.sourceFrame = new WebInspector.SourceFrame(null, this._addBreakpoint.bind(this));
     33    this.sourceFrame = new WebInspector.SourceFrame(this._addBreakpoint.bind(this));
    3434
    3535    resource.addEventListener("finished", this._resourceLoadingFinished, this);
     
    5151        WebInspector.ResourceView.prototype.show.call(this, parentElement);
    5252        this.setupSourceFrameIfNeeded();
     53        this.resize();
    5354    },
    5455
     
    5758        WebInspector.View.prototype.hide.call(this);
    5859        this._currentSearchResultIndex = -1;
     60    },
     61
     62    resize: function()
     63    {
     64        if (this._sourceFrameSetup)
     65            this.sourceFrame.resize();
    5966    },
    6067
     
    7784
    7885        delete this._frameNeedsSetup;
    79         this.sourceFrame.addEventListener("content loaded", this._contentLoaded, this);
    80         InspectorFrontendHost.addResourceSourceToFrame(this.resource.identifier, this.sourceFrame.element);
     86        WebInspector.getResourceContent(this.resource.identifier, this._contentLoaded.bind(this));
    8187    },
    8288   
    83     _contentLoaded: function()
    84     {
    85         delete this._frameNeedsSetup;
    86         this.sourceFrame.removeEventListener("content loaded", this._contentLoaded, this);
    87        
    88         if (this.resource.type === WebInspector.Resource.Type.Script
    89             || this.resource.mimeType === "application/json"
    90             || this.resource.mimeType === "application/javascript"
    91             || /\.js(on)?$/.test(this.resource.lastPathComponent) ) {
    92             this.sourceFrame.addEventListener("syntax highlighting complete", this._syntaxHighlightingComplete, this);
    93             this.sourceFrame.syntaxHighlightJavascript();
    94         } else if (this.resource.type === WebInspector.Resource.Type.Stylesheet
    95             || this.resource.mimeType === "text/css"
    96             || /\.css$/.test(this.resource.lastPathComponent) ) {
    97             this.sourceFrame.addEventListener("syntax highlighting complete", this._syntaxHighlightingComplete, this);
    98             this.sourceFrame.syntaxHighlightCSS();
    99         } else
    100             this._sourceFrameSetupFinished();
     89    _contentLoaded: function(content)
     90    {
     91        this.sourceFrame.setContent(this.resource.mimeType, content);
     92        this._sourceFrameSetupFinished();
    10193    },
    10294
     
    136128        this._currentSearchResultIndex = -1;
    137129        this._searchResults = [];
     130        this.sourceFrame.clearSelection();
    138131        delete this._delayedFindSearchMatches;
    139132    },
     
    144137        this.searchCanceled();
    145138
    146         var lineQueryRegex = /(^|\s)(?:#|line:\s*)(\d+)(\s|$)/i;
    147         var lineQueryMatch = query.match(lineQueryRegex);
    148         if (lineQueryMatch) {
    149             var lineToSearch = parseInt(lineQueryMatch[2]);
    150 
    151             // If there was a space before and after the line query part, replace with a space.
    152             // Otherwise replace with an empty string to eat the prefix or postfix space.
    153             var lineQueryReplacement = (lineQueryMatch[1] && lineQueryMatch[3] ? " " : "");
    154             var filterlessQuery = query.replace(lineQueryRegex, lineQueryReplacement);
    155         }
    156 
    157139        this._searchFinishedCallback = finishedCallback;
    158140
    159141        function findSearchMatches(query, finishedCallback)
    160142        {
    161             if (isNaN(lineToSearch)) {
    162                 // Search the whole document since there was no line to search.
    163                 this._searchResults = (InspectorFrontendHost.search(this.sourceFrame.element.contentDocument, query) || []);
    164             } else {
    165                 var sourceRow = this.sourceFrame.sourceRow(lineToSearch);
    166                 if (sourceRow) {
    167                     if (filterlessQuery) {
    168                         // There is still a query string, so search for that string in the line.
    169                         this._searchResults = (InspectorFrontendHost.search(sourceRow, filterlessQuery) || []);
    170                     } else {
    171                         // Match the whole line, since there was no remaining query string to match.
    172                         var rowRange = this.sourceFrame.element.contentDocument.createRange();
    173                         rowRange.selectNodeContents(sourceRow);
    174                         this._searchResults = [rowRange];
    175                     }
    176                 }
    177 
    178                 // Attempt to search for the whole query, just incase it matches a color like "#333".
    179                 var wholeQueryMatches = InspectorFrontendHost.search(this.sourceFrame.element.contentDocument, query);
    180                 if (wholeQueryMatches)
    181                     this._searchResults = this._searchResults.concat(wholeQueryMatches);
    182             }
    183 
     143            this._searchResults = this.sourceFrame.findSearchMatches(query);
    184144            if (this._searchResults)
    185145                finishedCallback(this, this._searchResults.length);
     
    268228            return;
    269229
    270         var selection = this.sourceFrame.element.contentWindow.getSelection();
    271         selection.removeAllRanges();
    272         selection.addRange(foundRange);
    273 
    274         if (foundRange.startContainer.scrollIntoViewIfNeeded)
    275             foundRange.startContainer.scrollIntoViewIfNeeded(true);
    276         else if (foundRange.startContainer.parentNode)
    277             foundRange.startContainer.parentNode.scrollIntoViewIfNeeded(true);
     230        this.sourceFrame.setSelection(foundRange);
    278231    },
    279232
     
    281234    {
    282235        this._sourceFrameSetup = true;
     236        this.resize();
    283237        if (this._delayedFindSearchMatches) {
    284238            this._delayedFindSearchMatches();
    285239            delete this._delayedFindSearchMatches;
    286240        }
    287     },
    288 
    289     _syntaxHighlightingComplete: function(event)
    290     {
    291         this._sourceFrameSetupFinished();
    292         this.sourceFrame.removeEventListener("syntax highlighting complete", null, this);
    293241    }
    294242}
  • trunk/WebCore/inspector/front-end/TextEditor.js

    r53856 r53941  
    5050    this._container.appendChild(this._sheet);
    5151
    52     this._clipboard = document.createElement("textarea");
    53     this._clipboard.className = "text-editor-clip";
    54     this._container.appendChild(this._clipboard);
    55 
    5652    var cursorElement = document.createElement("div");
    5753    cursorElement.className = "text-editor-cursor";
     
    139135    {
    140136        this._lineDecorator = lineDecorator;
     137    },
     138
     139    get selection()
     140    {
     141        return this._selection.range();
    141142    },
    142143
     
    515516        // Hide div-based cursor first.
    516517        this._cursor._cursorElement.style.display = "none";
    517         setTimeout(this._repaintOnScroll.bind(this), 0);
     518        setTimeout(this._repaintOnScroll.bind(this), 10);
    518519    },
    519520
     
    534535    _mouseDown: function(e)
    535536    {
     537        if (e.button === 2 || (this._isMac && e.ctrlKey))
     538            return;
     539
    536540        var location = this._caretForMouseEvent(e);
    537541
     
    575579            if (this._lineNumberDecorator.contextMenu(location.line, e))
    576580                return;
     581        } else {
     582            var range = this._selection.range();
     583            if (!range.isEmpty()) {
     584                var text = this._textModel.copyRange(range);
     585                var contextMenu = new WebInspector.ContextMenu();
     586                contextMenu.appendItem(WebInspector.UIString("Copy"), this._copy.bind(this));
     587                contextMenu.show(event);
     588            }
    577589        }
    578590    },
     
    582594        var lineNumber = Math.max(0, this._offsetToLine(e.offsetY) - 1);
    583595        var line = this._textModel.line(lineNumber);
    584         var offset = e.offsetX + this._scrollLeft - this._lineNumberWidth - this._digitWidth;
     596        var offset = e.offsetX + this._scrollLeft - this._lineNumberWidth;
    585597        return { line: lineNumber, column: this._columnForOffset(lineNumber, offset) };
    586598    },
     
    590602        var length = 0;
    591603        var line = this._textModel.line(lineNumber);
    592         for (var column = 0; column < line.length; ++column) {
    593             if (length > offset)
    594                 break;
    595             length += this._ctx.measureText(line.charAt(column)).width;
    596         }
    597         return column;
     604
     605        // First pretend it is monospace to get a quick guess.
     606        var charWidth = this._ctx.measureText("a").width;
     607        var index = Math.floor(offset / charWidth);
     608        var indexOffset = this._ctx.measureText(line.substring(0, index)).width;
     609        if (offset >= indexOffset && index < line.length && offset < indexOffset + this._ctx.measureText(line.charAt(index)).width)
     610            return index;
     611
     612        // Fallback to non-monospace.
     613        var delta = indexOffset < offset ? 1 : -1;
     614        while (index >=0 && index < line.length) {
     615            index += delta;
     616            indexOffset += delta * this._ctx.measureText(line.charAt(index)).width;
     617            if (offset >= indexOffset && offset < indexOffset + charWidth)
     618                return index;
     619        }
     620        return line.length;
    598621    },
    599622
     
    848871        var text = this._textModel.copyRange(range);
    849872
    850         this._clipboard.value = text;
    851         this._clipboard.select();
     873        function delayCopy()
     874        {
     875            InspectorFrontendHost.copyText(text);
     876        }
     877
     878        setTimeout(delayCopy);
     879        if (e)
     880            e.preventDefault();
    852881    },
    853882
     
    860889    _cut: function(e)
    861890    {
     891        if (this._readOnly) {
     892            e.preventDefault();
     893            return;
     894        }
     895
    862896        this._textModel.markUndoableState();
    863897        this._copy(e);
  • trunk/WebCore/inspector/front-end/WebKit.qrc

    r53846 r53941  
    6565    <file>SourceCSSTokenizer.js</file>
    6666    <file>SourceFrame.js</file>
    67     <file>SourceFrame2.js</file>
    6867    <file>SourceHTMLTokenizer.js</file>
    6968    <file>SourceJavaScriptTokenizer.js</file>
  • trunk/WebCore/inspector/front-end/inspector.html

    r53846 r53941  
    9494    <script type="text/javascript" src="ResourceView.js"></script>
    9595    <script type="text/javascript" src="SourceFrame.js"></script>
    96     <script type="text/javascript" src="SourceFrame2.js"></script>
    9796    <script type="text/javascript" src="SourceSyntaxHighlighter.js"></script>
    9897    <script type="text/javascript" src="CSSSourceSyntaxHighlighter.js"></script>
  • trunk/WebCore/inspector/front-end/textEditor.css

    r53856 r53941  
    3030    bottom:0;
    3131    overflow: auto;
    32 }
    33 
    34 .text-editor-clip {
    35     opacity: 0;
    36     position: absolute;
    37     top:0;
    38     left:0;
    39     pointer-events: none;
    4032}
    4133
Note: See TracChangeset for help on using the changeset viewer.