<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[160483] trunk/Source/WebInspectorUI</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/160483">160483</a></dd>
<dt>Author</dt> <dd>graouts@apple.com</dd>
<dt>Date</dt> <dd>2013-12-12 02:17:20 -0800 (Thu, 12 Dec 2013)</dd>
</dl>

<h3>Log Message</h3>
<pre>Web Inspector: allow editing of colors in CSS resources
https://bugs.webkit.org/show_bug.cgi?id=124364

Reviewed by Timothy Hatcher.

Identify colors in CSS and HTML resources so that hovering these colors shows a HoverMenu
allowing a ColorPicker hosted in a Popover to be shown to edit the hovered color.

* UserInterface/CSSStyleDeclarationTextEditor.js:
(WebInspector.CSSStyleDeclarationTextEditor.prototype._createColorSwatches):
Remove the code that goes through the lines of the CodeMirror editor to look for
color strings and replace it with a call to the .createColorMarkers() CodeMirror
extension in which the code was refactored. The callback passed to
.createColorMarkers() handles the CSSStyleDeclarationTextEditor-specific creation
of color swatches to show the popover, keeping the existing behavior of the Styles
sidebar panel.

* UserInterface/CodeMirrorAdditions.js:
Refactor existing code into two new CodeMirror extensions: .boundsForRange(), which
was previously defined on the CodeMirrorTokenTrackingController but was also needed
in the new CodeMirrorColorEditingController, and .createColorMarkers(), discussed above.

* UserInterface/CodeMirrorColorEditingController.js: Added.
(WebInspector.CodeMirrorColorEditingController):
New class used by SourceCodeTextEditor to coordinate the editing of a color in a CodeMirror
TextMarker by a ColorPicker hosted in a Popover shown by the activation of a HoverMenu. This
controller automatically gets the color set by the user using the ColorPicker and updates
the CodeMirror text editor with the new value. When the user presses the Esc. key while the
popover is shown, it's automatically dismissed and the original color is reset in the editor.

(WebInspector.CodeMirrorColorEditingController.prototype.get marker):
(WebInspector.CodeMirrorColorEditingController.prototype.get range):
(WebInspector.CodeMirrorColorEditingController.prototype.get delegate):
(WebInspector.CodeMirrorColorEditingController.prototype.set delegate):
Getters and setters for public properties.

(WebInspector.CodeMirrorColorEditingController.prototype.get color):
(WebInspector.CodeMirrorColorEditingController.prototype.set color):
Get and set the color for the edited color marker, replacing the text in the marker's range
upon setting.

(WebInspector.CodeMirrorColorEditingController.prototype.presentHoverMenu):
Public API allowing for a HoverMenu to be shown around the bounds of the TextMarker passed
in the constructor. This method is called from SourceCodeTextEditor when the
CodeMirrorTokenTrackingController identifies that a token that is part of a TextMarker is
hovered and that token is a color.

(WebInspector.CodeMirrorColorEditingController.prototype.dismissHoverMenu):
Public API allowing for the HoverMenu to be dismissed. This method is called when the
CodeMirrorTokenTrackingController identifies that its &quot;hoveredMarker&quot; is no longer being
hovered as well as when we identify that editing of the color has completed.

(WebInspector.CodeMirrorColorEditingController.prototype.handleEvent):
Event handler for the &quot;keydown&quot; event that are being listened to when the HoverMenu
is activated such that the Esc. key can be used to dimiss the popover and reset the
original color before any edits.

(WebInspector.CodeMirrorColorEditingController.prototype.hoverMenuButtonWasPressed):
Implementation of the HoverMenu delegation method used to show a Popover containing a
ColorPicker upon clicking on the color wheel attached to the HoverMenu. We also remember
the color set on the marker so that it may be restored when Esc. is pressed and used to
set the original state of the ColorPicker. The delegation method
colorEditingControllerDidStartEditing() is also called at this point, which the
SourceCodeTextEditor implements.

(WebInspector.CodeMirrorColorEditingController.prototype.didDismissPopover):
Implementation of the Popover delegation method used to identify that color editing has
completed. The delegation method colorEditingControllerDidFinishEditing() is called
at this point, which the SourceCodeTextEditor implements.

(WebInspector.CodeMirrorColorEditingController.prototype._colorPickerColorChanged):
Apply the color set in the color picker to the CodeMirror text editor.

* UserInterface/CodeMirrorTokenTrackingController.js:
Add two new modes to CodeMirrorTokenTrackingController. The first mode is &quot;None&quot; and is
the default, incurring no specific token handling behavior. The second mode is &quot;MarkedTokens&quot;
which identifies hover of a token contained in a CodeMirror TextMarker range. The new
&quot;MarkedTokens&quot; mode is used by SourceCodeTextEditor to identify when a marked color is being
hovered to display a HoverMenu.

(WebInspector.CodeMirrorTokenTrackingController):
(WebInspector.CodeMirrorTokenTrackingController.prototype.set mode):
Make &quot;None&quot; the new default mode for CodeMirrorTokenTrackingController.

(WebInspector.CodeMirrorTokenTrackingController.prototype.get hoveredMarker):
(WebInspector.CodeMirrorTokenTrackingController.prototype.set hoveredMarker):
(WebInspector.CodeMirrorTokenTrackingController.prototype._updateHoveredTokenInfo):
Check, when we have a &quot;hoveredMarker&quot; set on the CodeMirrorTokenTrackingController,
whether the &quot;hoveredMarker&quot; is still being hovered when there is no token at the current
mouse position. We can then determine when we're mousing out of the &quot;hoveredMarker&quot; and
notify the delegate via the new tokenTrackingControllerMouseOutOfHoveredMarker delegate
method. The SourceCodeTextEditor uses this method to dismiss its CodeMirrorColorEditingController.

(WebInspector.CodeMirrorTokenTrackingController.prototype._processNewHoveredToken):
Add support for the new &quot;MarkedTokens&quot; mode.

(WebInspector.CodeMirrorTokenTrackingController.prototype._processMarkedToken):
For the moment, use the same behavior as the existing &quot;MarkedTokens&quot; mode.

* UserInterface/Color.js:
(WebInspector.Color):
Add a new &quot;valid&quot; property to identify whether a color has any invalid (NaN) component. This property
is used by SourceCodeTextEditor to establish whether a hovered color marker is indeed set to a
valid color still.

(WebInspector.Color.prototype.copy):
New method to create an exact copy of a Color instance, used by CodeMirrorColorEditingController
to duplicate the edited color in case we need to revert it.

* UserInterface/HoverMenu.js:
(WebInspector.HoverMenu.prototype._handleClickEvent):
Rename hoverMenuWasActivated to hoverMenuButtonWasPressed per review feedback.

* UserInterface/Images/ColorIcon.png: Added.
* UserInterface/Images/ColorIcon@2x.png: Added.
New color wheel icon used to customize the HoverMenu shown by a CodeMirrorColorEditingController.

* UserInterface/Main.html:
Link to the new CodeMirrorColorEditingController.js file.

* UserInterface/SourceCodeTextEditor.css:
(.hover-menu.color):
(.hover-menu.color &gt; img):
Customize the HoverMenu shown by a CodeMirrorColorEditingController to use the new ColorIcon asset.

* UserInterface/SourceCodeTextEditor.js:
(WebInspector.SourceCodeTextEditor):
Add a new &quot;_ignoreContentDidChange&quot; ivar that increments and decrements to track when handling
of CodeMirror content changes should be disabled.

(WebInspector.SourceCodeTextEditor.prototype.close):
Adopt the new ._updateTokenTrackingControllerState() method to update the state of the
CodeMirrorTokenTrackingController.

(WebInspector.SourceCodeTextEditor.prototype.contentDidChange):
Override the new TextEditor public API called when content in the CodeMirror text editor is changed.
We use this method to process any newly added line to create any newly added color marker.

(WebInspector.SourceCodeTextEditor.prototype._contentDidPopulate):
(WebInspector.SourceCodeTextEditor.prototype._debuggerDidPause):
(WebInspector.SourceCodeTextEditor.prototype._debuggerDidResume):
(WebInspector.SourceCodeTextEditor.prototype._sourceCodeSourceMapAdded):
Adopt the new ._updateTokenTrackingControllerState() method to update the state of the
CodeMirrorTokenTrackingController.

(WebInspector.SourceCodeTextEditor.prototype._updateTokenTrackingControllerState):
New method acting as the only point where we check the state of the text editor and set the right
mode and settings on the CodeMirrorTokenTrackingController, including setting the new &quot;MarkedTokens&quot;
mode when we have color markers, as determined by ._hasColorMarkers().

(WebInspector.SourceCodeTextEditor.prototype._hasColorMarkers):
Check whether any of the TextMarkers set on the CodeMirror text editor were created for a color.

(WebInspector.SourceCodeTextEditor.prototype.tokenTrackingControllerHighlightedRangeWasClicked):
Check the CodeMirrorTokenTrackingController mode rather than the removed &quot;_jumpToSymbolTrackingModeEnabled&quot;
ivar to identify we're in the &quot;NonSymbolTokens&quot; mode.

(WebInspector.SourceCodeTextEditor.prototype.tokenTrackingControllerNewHighlightCandidate):
Refactor method to use the CodeMirrorTokenTrackingController mode to branch into mode-specific code
and add a new branch for the new &quot;MarkedTokens&quot; mode where we check if the newly hovered token
is part of a color TextMarker range.

(WebInspector.SourceCodeTextEditor.prototype.tokenTrackingControllerMouseOutOfHoveredMarker):
Implement this new CodeMirrorTokenTrackingController delegation method to dismiss the
CodeMirrorColorEditingController as we identify we're no longer hovering over the TextMarker
for which the CodeMirrorColorEditingController was created.

(WebInspector.SourceCodeTextEditor.prototype._showPopover):
Adopt the new TextEditor boundsForRange() method.

(WebInspector.SourceCodeTextEditor.prototype._updateColorMarkers):
Harness the new TextEditor createColorMarkers() method to create new TextMarkers for the provided
line, or the entire text editor content if none provided. We then immediately call _updateTokenTrackingControllerState()
so that the new &quot;MarkedTokens&quot; mode is entered in case color TextMarkers were created for the first
time for this text editor.

(WebInspector.SourceCodeTextEditor.prototype._tokenTrackingControllerHighlightedMarkedExpression):
Called when we've identified the CodeMirrorTokenTrackingController highlighted a TextMarker. We check
if any of the hovered TextMarkers are for a color, and in this case create a CodeMirrorColorEditingController
to coordinate the display of a ColorPicker in a Popover to edit the hovered color token. We also check
whether the hovered marker still contains a valid color, clearing the marker in case it was edited to
no longer contain a color.

(WebInspector.SourceCodeTextEditor.prototype._dismissCodeMirrorColorEditingController):
Used to dismiss the CodeMirrorColorEditingController, if previously presented, and reset some internal state.

(WebInspector.SourceCodeTextEditor.prototype.colorEditingControllerDidStartEditing):
Implement this CodeMirrorColorEditingController delegation method to temporarily disable the
CodeMirrorTokenTrackingController while we edit the color with the ColorPicker, remove
the TextMarker for the edited color and instruct that content changes should be ignored
such that we act on the complete set of color edits upon completion.

(WebInspector.SourceCodeTextEditor.prototype.colorEditingControllerDidFinishEditing):
Update color markers for the edited line such that any color edits are correctly updated for
the future and so that, as a side-effect, the CodeMirrorColorEditingController is reset to the
appropriate mode depending on whether color TextMarkers are indeed available, resetting states
that may have been altered by colorEditingControllerDidStartEditing().

* UserInterface/TextEditor.js:
(WebInspector.TextEditor.prototype.contentDidChange):
New public method meant to be overriden by subclasses, added for the use of SourceCodeTextEditor, exposing
the list of TextRanges affected by the content change, both in the context of the old content and new content.

(WebInspector.TextEditor.prototype.boundsForRange):
(WebInspector.TextEditor.prototype.get markers):
(WebInspector.TextEditor.prototype.findMarkersAtPosition):
(WebInspector.TextEditor.prototype.createColorMarkers):
(WebInspector.TextEditor.prototype.colorEditingControllerForMarker):
New public methods calling into the CodeMirror private ivar for the benefit of SourceCodeTextEditor.

(WebInspector.TextEditor.prototype._contentChanged):
Call the new contentDidChange() method.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebInspectorUIChangeLog">trunk/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceCSSStyleDeclarationTextEditorjs">trunk/Source/WebInspectorUI/UserInterface/CSSStyleDeclarationTextEditor.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceCodeMirrorAdditionsjs">trunk/Source/WebInspectorUI/UserInterface/CodeMirrorAdditions.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceCodeMirrorTokenTrackingControllerjs">trunk/Source/WebInspectorUI/UserInterface/CodeMirrorTokenTrackingController.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceColorjs">trunk/Source/WebInspectorUI/UserInterface/Color.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceHoverMenujs">trunk/Source/WebInspectorUI/UserInterface/HoverMenu.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceMainhtml">trunk/Source/WebInspectorUI/UserInterface/Main.html</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceSourceCodeTextEditorcss">trunk/Source/WebInspectorUI/UserInterface/SourceCodeTextEditor.css</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceSourceCodeTextEditorjs">trunk/Source/WebInspectorUI/UserInterface/SourceCodeTextEditor.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceTextEditorjs">trunk/Source/WebInspectorUI/UserInterface/TextEditor.js</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceCodeMirrorColorEditingControllerjs">trunk/Source/WebInspectorUI/UserInterface/CodeMirrorColorEditingController.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceImagesColorIconpng">trunk/Source/WebInspectorUI/UserInterface/Images/ColorIcon.png</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceImagesColorIcon2xpng">trunk/Source/WebInspectorUI/UserInterface/Images/ColorIcon@2x.png</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (160482 => 160483)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/ChangeLog        2013-12-12 10:10:36 UTC (rev 160482)
+++ trunk/Source/WebInspectorUI/ChangeLog        2013-12-12 10:17:20 UTC (rev 160483)
</span><span class="lines">@@ -1,3 +1,218 @@
</span><ins>+2013-12-12  Antoine Quint  &lt;graouts@apple.com&gt;
+
+        Web Inspector: allow editing of colors in CSS resources
+        https://bugs.webkit.org/show_bug.cgi?id=124364
+
+        Reviewed by Timothy Hatcher.
+
+        Identify colors in CSS and HTML resources so that hovering these colors shows a HoverMenu
+        allowing a ColorPicker hosted in a Popover to be shown to edit the hovered color.
+
+        * UserInterface/CSSStyleDeclarationTextEditor.js:
+        (WebInspector.CSSStyleDeclarationTextEditor.prototype._createColorSwatches):
+        Remove the code that goes through the lines of the CodeMirror editor to look for
+        color strings and replace it with a call to the .createColorMarkers() CodeMirror
+        extension in which the code was refactored. The callback passed to
+        .createColorMarkers() handles the CSSStyleDeclarationTextEditor-specific creation
+        of color swatches to show the popover, keeping the existing behavior of the Styles
+        sidebar panel.
+
+        * UserInterface/CodeMirrorAdditions.js:
+        Refactor existing code into two new CodeMirror extensions: .boundsForRange(), which
+        was previously defined on the CodeMirrorTokenTrackingController but was also needed
+        in the new CodeMirrorColorEditingController, and .createColorMarkers(), discussed above.
+
+        * UserInterface/CodeMirrorColorEditingController.js: Added.
+        (WebInspector.CodeMirrorColorEditingController):
+        New class used by SourceCodeTextEditor to coordinate the editing of a color in a CodeMirror
+        TextMarker by a ColorPicker hosted in a Popover shown by the activation of a HoverMenu. This
+        controller automatically gets the color set by the user using the ColorPicker and updates
+        the CodeMirror text editor with the new value. When the user presses the Esc. key while the
+        popover is shown, it's automatically dismissed and the original color is reset in the editor.
+
+        (WebInspector.CodeMirrorColorEditingController.prototype.get marker):
+        (WebInspector.CodeMirrorColorEditingController.prototype.get range):
+        (WebInspector.CodeMirrorColorEditingController.prototype.get delegate):
+        (WebInspector.CodeMirrorColorEditingController.prototype.set delegate):
+        Getters and setters for public properties.
+
+        (WebInspector.CodeMirrorColorEditingController.prototype.get color):
+        (WebInspector.CodeMirrorColorEditingController.prototype.set color):
+        Get and set the color for the edited color marker, replacing the text in the marker's range
+        upon setting.
+
+        (WebInspector.CodeMirrorColorEditingController.prototype.presentHoverMenu):
+        Public API allowing for a HoverMenu to be shown around the bounds of the TextMarker passed
+        in the constructor. This method is called from SourceCodeTextEditor when the
+        CodeMirrorTokenTrackingController identifies that a token that is part of a TextMarker is
+        hovered and that token is a color.
+
+        (WebInspector.CodeMirrorColorEditingController.prototype.dismissHoverMenu):
+        Public API allowing for the HoverMenu to be dismissed. This method is called when the
+        CodeMirrorTokenTrackingController identifies that its &quot;hoveredMarker&quot; is no longer being
+        hovered as well as when we identify that editing of the color has completed.
+
+        (WebInspector.CodeMirrorColorEditingController.prototype.handleEvent):
+        Event handler for the &quot;keydown&quot; event that are being listened to when the HoverMenu
+        is activated such that the Esc. key can be used to dimiss the popover and reset the
+        original color before any edits.
+
+        (WebInspector.CodeMirrorColorEditingController.prototype.hoverMenuButtonWasPressed):
+        Implementation of the HoverMenu delegation method used to show a Popover containing a
+        ColorPicker upon clicking on the color wheel attached to the HoverMenu. We also remember
+        the color set on the marker so that it may be restored when Esc. is pressed and used to
+        set the original state of the ColorPicker. The delegation method
+        colorEditingControllerDidStartEditing() is also called at this point, which the
+        SourceCodeTextEditor implements.
+
+        (WebInspector.CodeMirrorColorEditingController.prototype.didDismissPopover):
+        Implementation of the Popover delegation method used to identify that color editing has
+        completed. The delegation method colorEditingControllerDidFinishEditing() is called
+        at this point, which the SourceCodeTextEditor implements.
+
+        (WebInspector.CodeMirrorColorEditingController.prototype._colorPickerColorChanged):
+        Apply the color set in the color picker to the CodeMirror text editor.
+
+        * UserInterface/CodeMirrorTokenTrackingController.js:
+        Add two new modes to CodeMirrorTokenTrackingController. The first mode is &quot;None&quot; and is
+        the default, incurring no specific token handling behavior. The second mode is &quot;MarkedTokens&quot;
+        which identifies hover of a token contained in a CodeMirror TextMarker range. The new
+        &quot;MarkedTokens&quot; mode is used by SourceCodeTextEditor to identify when a marked color is being
+        hovered to display a HoverMenu.
+
+        (WebInspector.CodeMirrorTokenTrackingController):
+        (WebInspector.CodeMirrorTokenTrackingController.prototype.set mode):
+        Make &quot;None&quot; the new default mode for CodeMirrorTokenTrackingController.
+
+        (WebInspector.CodeMirrorTokenTrackingController.prototype.get hoveredMarker):
+        (WebInspector.CodeMirrorTokenTrackingController.prototype.set hoveredMarker):
+        (WebInspector.CodeMirrorTokenTrackingController.prototype._updateHoveredTokenInfo):
+        Check, when we have a &quot;hoveredMarker&quot; set on the CodeMirrorTokenTrackingController,
+        whether the &quot;hoveredMarker&quot; is still being hovered when there is no token at the current
+        mouse position. We can then determine when we're mousing out of the &quot;hoveredMarker&quot; and
+        notify the delegate via the new tokenTrackingControllerMouseOutOfHoveredMarker delegate
+        method. The SourceCodeTextEditor uses this method to dismiss its CodeMirrorColorEditingController.
+
+        (WebInspector.CodeMirrorTokenTrackingController.prototype._processNewHoveredToken):
+        Add support for the new &quot;MarkedTokens&quot; mode.
+
+        (WebInspector.CodeMirrorTokenTrackingController.prototype._processMarkedToken):
+        For the moment, use the same behavior as the existing &quot;MarkedTokens&quot; mode.
+
+        * UserInterface/Color.js:
+        (WebInspector.Color):
+        Add a new &quot;valid&quot; property to identify whether a color has any invalid (NaN) component. This property
+        is used by SourceCodeTextEditor to establish whether a hovered color marker is indeed set to a
+        valid color still.
+
+        (WebInspector.Color.prototype.copy):
+        New method to create an exact copy of a Color instance, used by CodeMirrorColorEditingController
+        to duplicate the edited color in case we need to revert it.
+
+        * UserInterface/HoverMenu.js:
+        (WebInspector.HoverMenu.prototype._handleClickEvent):
+        Rename hoverMenuWasActivated to hoverMenuButtonWasPressed per review feedback.
+
+        * UserInterface/Images/ColorIcon.png: Added.
+        * UserInterface/Images/ColorIcon@2x.png: Added.
+        New color wheel icon used to customize the HoverMenu shown by a CodeMirrorColorEditingController.
+
+        * UserInterface/Main.html:
+        Link to the new CodeMirrorColorEditingController.js file.
+
+        * UserInterface/SourceCodeTextEditor.css:
+        (.hover-menu.color):
+        (.hover-menu.color &gt; img):
+        Customize the HoverMenu shown by a CodeMirrorColorEditingController to use the new ColorIcon asset.
+
+        * UserInterface/SourceCodeTextEditor.js:
+        (WebInspector.SourceCodeTextEditor):
+        Add a new &quot;_ignoreContentDidChange&quot; ivar that increments and decrements to track when handling
+        of CodeMirror content changes should be disabled.
+
+        (WebInspector.SourceCodeTextEditor.prototype.close):
+        Adopt the new ._updateTokenTrackingControllerState() method to update the state of the
+        CodeMirrorTokenTrackingController.
+
+        (WebInspector.SourceCodeTextEditor.prototype.contentDidChange):
+        Override the new TextEditor public API called when content in the CodeMirror text editor is changed.
+        We use this method to process any newly added line to create any newly added color marker.
+
+        (WebInspector.SourceCodeTextEditor.prototype._contentDidPopulate):
+        (WebInspector.SourceCodeTextEditor.prototype._debuggerDidPause):
+        (WebInspector.SourceCodeTextEditor.prototype._debuggerDidResume):
+        (WebInspector.SourceCodeTextEditor.prototype._sourceCodeSourceMapAdded):
+        Adopt the new ._updateTokenTrackingControllerState() method to update the state of the
+        CodeMirrorTokenTrackingController.
+
+        (WebInspector.SourceCodeTextEditor.prototype._updateTokenTrackingControllerState):
+        New method acting as the only point where we check the state of the text editor and set the right
+        mode and settings on the CodeMirrorTokenTrackingController, including setting the new &quot;MarkedTokens&quot;
+        mode when we have color markers, as determined by ._hasColorMarkers().
+
+        (WebInspector.SourceCodeTextEditor.prototype._hasColorMarkers):
+        Check whether any of the TextMarkers set on the CodeMirror text editor were created for a color.
+
+        (WebInspector.SourceCodeTextEditor.prototype.tokenTrackingControllerHighlightedRangeWasClicked):
+        Check the CodeMirrorTokenTrackingController mode rather than the removed &quot;_jumpToSymbolTrackingModeEnabled&quot;
+        ivar to identify we're in the &quot;NonSymbolTokens&quot; mode.
+
+        (WebInspector.SourceCodeTextEditor.prototype.tokenTrackingControllerNewHighlightCandidate):
+        Refactor method to use the CodeMirrorTokenTrackingController mode to branch into mode-specific code
+        and add a new branch for the new &quot;MarkedTokens&quot; mode where we check if the newly hovered token
+        is part of a color TextMarker range.
+
+        (WebInspector.SourceCodeTextEditor.prototype.tokenTrackingControllerMouseOutOfHoveredMarker):
+        Implement this new CodeMirrorTokenTrackingController delegation method to dismiss the
+        CodeMirrorColorEditingController as we identify we're no longer hovering over the TextMarker
+        for which the CodeMirrorColorEditingController was created.
+
+        (WebInspector.SourceCodeTextEditor.prototype._showPopover):
+        Adopt the new TextEditor boundsForRange() method.
+
+        (WebInspector.SourceCodeTextEditor.prototype._updateColorMarkers):
+        Harness the new TextEditor createColorMarkers() method to create new TextMarkers for the provided
+        line, or the entire text editor content if none provided. We then immediately call _updateTokenTrackingControllerState()
+        so that the new &quot;MarkedTokens&quot; mode is entered in case color TextMarkers were created for the first
+        time for this text editor.
+
+        (WebInspector.SourceCodeTextEditor.prototype._tokenTrackingControllerHighlightedMarkedExpression):
+        Called when we've identified the CodeMirrorTokenTrackingController highlighted a TextMarker. We check
+        if any of the hovered TextMarkers are for a color, and in this case create a CodeMirrorColorEditingController
+        to coordinate the display of a ColorPicker in a Popover to edit the hovered color token. We also check
+        whether the hovered marker still contains a valid color, clearing the marker in case it was edited to
+        no longer contain a color.
+
+        (WebInspector.SourceCodeTextEditor.prototype._dismissCodeMirrorColorEditingController):
+        Used to dismiss the CodeMirrorColorEditingController, if previously presented, and reset some internal state.
+
+        (WebInspector.SourceCodeTextEditor.prototype.colorEditingControllerDidStartEditing):
+        Implement this CodeMirrorColorEditingController delegation method to temporarily disable the
+        CodeMirrorTokenTrackingController while we edit the color with the ColorPicker, remove
+        the TextMarker for the edited color and instruct that content changes should be ignored
+        such that we act on the complete set of color edits upon completion.
+
+        (WebInspector.SourceCodeTextEditor.prototype.colorEditingControllerDidFinishEditing):
+        Update color markers for the edited line such that any color edits are correctly updated for
+        the future and so that, as a side-effect, the CodeMirrorColorEditingController is reset to the
+        appropriate mode depending on whether color TextMarkers are indeed available, resetting states
+        that may have been altered by colorEditingControllerDidStartEditing().
+
+        * UserInterface/TextEditor.js:
+        (WebInspector.TextEditor.prototype.contentDidChange):
+        New public method meant to be overriden by subclasses, added for the use of SourceCodeTextEditor, exposing
+        the list of TextRanges affected by the content change, both in the context of the old content and new content.
+
+        (WebInspector.TextEditor.prototype.boundsForRange):
+        (WebInspector.TextEditor.prototype.get markers):
+        (WebInspector.TextEditor.prototype.findMarkersAtPosition):
+        (WebInspector.TextEditor.prototype.createColorMarkers):
+        (WebInspector.TextEditor.prototype.colorEditingControllerForMarker):
+        New public methods calling into the CodeMirror private ivar for the benefit of SourceCodeTextEditor.
+
+        (WebInspector.TextEditor.prototype._contentChanged):
+        Call the new contentDidChange() method.
+
</ins><span class="cx"> 2013-12-05  Seokju Kwon  &lt;seokju@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: Remove 'cookiesString' output from Page.getCookies
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceCSSStyleDeclarationTextEditorjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/CSSStyleDeclarationTextEditor.js (160482 => 160483)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/CSSStyleDeclarationTextEditor.js        2013-12-12 10:10:36 UTC (rev 160482)
+++ trunk/Source/WebInspectorUI/UserInterface/CSSStyleDeclarationTextEditor.js        2013-12-12 10:17:20 UTC (rev 160483)
</span><span class="lines">@@ -390,69 +390,22 @@
</span><span class="cx">     {
</span><span class="cx">         function update()
</span><span class="cx">         {
</span><del>-            // Matches rgba(0, 0, 0, 0.5), rgb(0, 0, 0), hsl(), hsla(), #fff, #ffffff, white
-            const colorRegex = /((?:rgb|hsl)a?\([^)]+\)|#[0-9a-fA-F]{6}|#[0-9a-fA-F]{3}|\b\w+\b(?![-.]))/g;
-
-            var start = typeof lineNumber === &quot;number&quot; ? lineNumber : 0;
-            var end = typeof lineNumber === &quot;number&quot; ? lineNumber + 1 : this._codeMirror.lineCount();
-
</del><span class="cx">             // Look for color strings and add swatches in front of them.
</span><del>-            for (var i = start; i &lt; end; ++i) {
-                var lineContent = this._codeMirror.getLine(i);
-
-                var match = colorRegex.exec(lineContent);
-                while (match) {
-
-                    // Act as a negative look-behind and disallow the color from being prefixing with certain characters.
-                    if (match.index &gt; 0 &amp;&amp; /[-.]/.test(lineContent[match.index - 1])) {
-                        match = colorRegex.exec(lineContent);
-                        continue;
-                    }
-
-                    var from = {line: i, ch: match.index};
-                    var to = {line: i, ch: match.index + match[0].length};
-
-                    var foundColorMarker = false;
-                    var marks = this._codeMirror.findMarksAt(to);
-                    for (var j = 0; j &lt; marks.length; ++j) {
-                        if (!marks[j].__markedColor)
-                            continue;
-                        foundColorMarker = true;
-                        break;
-                    }
-
-                    if (foundColorMarker) {
-                        match = colorRegex.exec(lineContent);
-                        continue;
-                    }
-
-
-                    var color = WebInspector.Color.fromString(match[0]);
-                    if (!color) {
-                        match = colorRegex.exec(lineContent);
-                        continue;
-                    }
-
-                    var swatchElement = document.createElement(&quot;span&quot;);
-                    swatchElement.title = WebInspector.UIString(&quot;Click to open a colorpicker. Shift-click to change color format.&quot;);
-                    swatchElement.className = WebInspector.CSSStyleDeclarationTextEditor.ColorSwatchElementStyleClassName;
-                    swatchElement.addEventListener(&quot;click&quot;, this._colorSwatchClicked.bind(this));
-
-                    var swatchInnerElement = document.createElement(&quot;span&quot;);
-                    swatchInnerElement.style.backgroundColor = match[0];
-                    swatchElement.appendChild(swatchInnerElement);
-
-                    var swatchMarker = this._codeMirror.setUniqueBookmark(from, swatchElement);
-
-                    var colorTextMarker = this._codeMirror.markText(from, to);
-                    colorTextMarker.__markedColor = true;
-
-                    swatchInnerElement.__colorTextMarker = colorTextMarker;
-                    swatchInnerElement.__color = color;
-
-                    match = colorRegex.exec(lineContent);
-                }
-            }
</del><ins>+            this._codeMirror.createColorMarkers(lineNumber, function(marker, color, colorString) {
+                var swatchElement = document.createElement(&quot;span&quot;);
+                swatchElement.title = WebInspector.UIString(&quot;Click to open a colorpicker. Shift-click to change color format.&quot;);
+                swatchElement.className = WebInspector.CSSStyleDeclarationTextEditor.ColorSwatchElementStyleClassName;
+                swatchElement.addEventListener(&quot;click&quot;, this._colorSwatchClicked.bind(this));
+                            
+                var swatchInnerElement = document.createElement(&quot;span&quot;);
+                swatchInnerElement.style.backgroundColor = colorString;
+                swatchElement.appendChild(swatchInnerElement);
+                            
+                var swatchMarker = this._codeMirror.setUniqueBookmark(marker.find().from, swatchElement);
+                            
+                swatchInnerElement.__colorTextMarker = marker;
+                swatchInnerElement.__color = color;
+            }.bind(this));
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (nonatomic)
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceCodeMirrorAdditionsjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/CodeMirrorAdditions.js (160482 => 160483)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/CodeMirrorAdditions.js        2013-12-12 10:10:36 UTC (rev 160482)
+++ trunk/Source/WebInspectorUI/UserInterface/CodeMirrorAdditions.js        2013-12-12 10:17:20 UTC (rev 160483)
</span><span class="lines">@@ -418,6 +418,71 @@
</span><span class="cx">             return CodeMirror.Pass;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    CodeMirror.defineExtension(&quot;boundsForRange&quot;, function(range) {
+        var firstCharCoords = this.cursorCoords(range.start);
+        var lastCharCoords = this.cursorCoords(range.end);
+        return new WebInspector.Rect(firstCharCoords.left, firstCharCoords.top, lastCharCoords.right - firstCharCoords.left, firstCharCoords.bottom - firstCharCoords.top);
+    });
+
+    CodeMirror.defineExtension(&quot;createColorMarkers&quot;, function(lineNumber, callback) {
+        var createdMarkers = [];
+
+        var start = typeof lineNumber === &quot;number&quot; ? lineNumber : 0;
+        var end = typeof lineNumber === &quot;number&quot; ? lineNumber + 1 : this.lineCount();
+
+        // Matches rgba(0, 0, 0, 0.5), rgb(0, 0, 0), hsl(), hsla(), #fff, #ffffff, white
+        const colorRegex = /((?:rgb|hsl)a?\([^)]+\)|#[0-9a-fA-F]{6}|#[0-9a-fA-F]{3}|\b\w+\b(?![-.]))/g;
+
+        for (var lineNumber = start; lineNumber &lt; end; ++lineNumber) {
+            var lineContent = this.getLine(lineNumber);
+            var match = colorRegex.exec(lineContent);
+            while (match) {
+
+                // Act as a negative look-behind and disallow the color from being prefixing with certain characters.
+                if (match.index &gt; 0 &amp;&amp; /[-.]/.test(lineContent[match.index - 1])) {
+                    match = colorRegex.exec(lineContent);
+                    continue;
+                }
+
+                var from = {line: lineNumber, ch: match.index};
+                var to = {line: lineNumber, ch: match.index + match[0].length};
+
+                var foundColorMarker = false;
+                var markers = this.findMarksAt(to);
+                for (var j = 0; j &lt; markers.length; ++j) {
+                    if (!markers[j].__markedColor)
+                        continue;
+                    foundColorMarker = true;
+                    break;
+                }
+
+                if (foundColorMarker) {
+                    match = colorRegex.exec(lineContent);
+                    continue;
+                }
+
+                var colorString = match[0];
+                var color = WebInspector.Color.fromString(colorString);
+                if (!color) {
+                    match = colorRegex.exec(lineContent);
+                    continue;
+                }
+
+                var marker = this.markText(from, to);
+                marker.__markedColor = true;
+
+                createdMarkers.push(marker);
+
+                if (callback)
+                    callback(marker, color, colorString);
+
+                match = colorRegex.exec(lineContent);
+            }
+        }
+
+        return createdMarkers;
+    });
+
</ins><span class="cx">     function ignoreKey(codeMirror)
</span><span class="cx">     {
</span><span class="cx">         // Do nothing to ignore the key.
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceCodeMirrorColorEditingControllerjs"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/CodeMirrorColorEditingController.js (0 => 160483)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/CodeMirrorColorEditingController.js                                (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/CodeMirrorColorEditingController.js        2013-12-12 10:17:20 UTC (rev 160483)
</span><span class="lines">@@ -0,0 +1,149 @@
</span><ins>+/*
+ * Copyright (C) 2013 Apple 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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.
+ */
+
+WebInspector.CodeMirrorColorEditingController = function(codeMirror, marker)
+{
+    WebInspector.Object.call(this);
+
+    this._codeMirror = codeMirror;
+    this._marker = marker;
+    this._delegate = null;
+
+    this._range = marker.find();
+
+    this._color = WebInspector.Color.fromString(codeMirror.getRange(this._range.from, this._range.to));
+
+    this._keyboardShortcutEsc = new WebInspector.KeyboardShortcut(null, WebInspector.KeyboardShortcut.Key.Escape);
+}
+
+WebInspector.CodeMirrorColorEditingController.prototype = {
+    constructor: WebInspector.CodeMirrorColorEditingController,
+    __proto__: WebInspector.Object.prototype,
+    
+    // Public
+    
+    get marker()
+    {
+        return this._marker;
+    },
+    
+    get range()
+    {
+        return this._range;
+    },
+
+    get color()
+    {
+        return this._color;
+    },
+    
+    set color(color)
+    {
+        var colorText = color.toString();
+        this._codeMirror.replaceRange(colorText, this._range.from, this._range.to);
+        this._range.to.ch = this._range.from.ch + colorText.length;
+
+        this._color = color;
+    },
+
+    get delegate()
+    {
+        return this._delegate;
+    },
+
+    set delegate(delegate)
+    {
+        this._delegate = delegate;
+    },
+    
+    presentHoverMenu: function()
+    {
+        this._hoverMenu = new WebInspector.HoverMenu(this);
+        this._hoverMenu.element.classList.add(&quot;color&quot;);
+        this._bounds = this._codeMirror.boundsForRange({
+            start: this._range.from,
+            end: this._range.to
+        });
+        this._hoverMenu.present(this._bounds);
+    },
+
+    dismissHoverMenu: function()
+    {
+        this._hoverMenu.dismiss();
+    },
+
+    // Protected
+
+    handleEvent: function(event)
+    {
+        if (!this._keyboardShortcutEsc.matchesEvent(event) || !this._popover.visible)
+            return;
+        
+        this.color = this._originalColor;
+        this._popover.dismiss();
+
+        event.stopPropagation();
+        event.preventDefault();
+    },
+
+    hoverMenuButtonWasPressed: function(hoverMenu)
+    {
+        var colorPicker = new WebInspector.ColorPicker;
+        colorPicker.addEventListener(WebInspector.ColorPicker.Event.ColorChanged, this._colorPickerColorChanged, this);
+
+        this._popover = new WebInspector.Popover(this);
+        this._popover.content = colorPicker.element;
+        this._popover.present(this._bounds.pad(2), [WebInspector.RectEdge.MAX_Y, WebInspector.RectEdge.MAX_X]);
+
+        window.addEventListener(&quot;keydown&quot;, this, true);
+
+        colorPicker.color = this._color;
+
+        hoverMenu.dismiss();
+
+        if (this._delegate &amp;&amp; typeof this._delegate.colorEditingControllerDidStartEditing === &quot;function&quot;)
+            this._delegate.colorEditingControllerDidStartEditing(this);
+
+        this._originalColor = this._color.copy();
+    },
+    
+    didDismissPopover: function(popover)
+    {
+        delete this._popover;
+        delete this._originalColor;
+
+        window.removeEventListener(&quot;keydown&quot;, this, true);
+
+        if (this._delegate &amp;&amp; typeof this._delegate.colorEditingControllerDidFinishEditing === &quot;function&quot;)
+            this._delegate.colorEditingControllerDidFinishEditing(this);
+    },
+    
+    // Private
+    
+    _colorPickerColorChanged: function(event)
+    {
+        this.color = event.target.color;
+    }    
+}
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceCodeMirrorTokenTrackingControllerjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/CodeMirrorTokenTrackingController.js (160482 => 160483)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/CodeMirrorTokenTrackingController.js        2013-12-12 10:10:36 UTC (rev 160482)
+++ trunk/Source/WebInspectorUI/UserInterface/CodeMirrorTokenTrackingController.js        2013-12-12 10:17:20 UTC (rev 160483)
</span><span class="lines">@@ -31,7 +31,7 @@
</span><span class="cx"> 
</span><span class="cx">     this._codeMirror = codeMirror;
</span><span class="cx">     this._delegate = delegate || null;
</span><del>-    this._mode = WebInspector.CodeMirrorTokenTrackingController.Mode.NonSymbolTokens;
</del><ins>+    this._mode = WebInspector.CodeMirrorTokenTrackingController.Mode.None;
</ins><span class="cx"> 
</span><span class="cx">     this._mouseOverDelayDuration = 0;
</span><span class="cx">     this._mouseOutReleaseDelayDuration = 0;
</span><span class="lines">@@ -40,13 +40,16 @@
</span><span class="cx">     this._enabled = false;
</span><span class="cx">     this._tracking = false;
</span><span class="cx">     this._hoveredTokenInfo = null;
</span><ins>+    this._hoveredMarker = null;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> WebInspector.CodeMirrorTokenTrackingController.JumpToSymbolHighlightStyleClassName = &quot;jump-to-symbol-highlight&quot;;
</span><span class="cx"> 
</span><span class="cx"> WebInspector.CodeMirrorTokenTrackingController.Mode = {
</span><ins>+    None: &quot;none&quot;,
</ins><span class="cx">     NonSymbolTokens: &quot;non-symbol-tokens&quot;,
</span><span class="cx">     JavaScriptExpression: &quot;javascript-expression&quot;,
</span><ins>+    MarkedTokens: &quot;marked-tokens&quot;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> WebInspector.CodeMirrorTokenTrackingController.prototype = {
</span><span class="lines">@@ -94,11 +97,11 @@
</span><span class="cx">         return this._mode;
</span><span class="cx">     },
</span><span class="cx"> 
</span><del>-    set mode(x)
</del><ins>+    set mode(mode)
</ins><span class="cx">     {
</span><span class="cx">         var oldMode = this._mode;
</span><span class="cx"> 
</span><del>-        this._mode = x || WebInspector.CodeMirrorTokenTrackingController.Mode.NonSymbolTokens;
</del><ins>+        this._mode = mode || WebInspector.CodeMirrorTokenTrackingController.Mode.None;
</ins><span class="cx"> 
</span><span class="cx">         if (oldMode !== this._mode &amp;&amp; this._tracking &amp;&amp; this._hoveredTokenInfo)
</span><span class="cx">             this._processNewHoveredToken();
</span><span class="lines">@@ -141,6 +144,16 @@
</span><span class="cx">         return this._candidate;
</span><span class="cx">     },
</span><span class="cx"> 
</span><ins>+    get hoveredMarker()
+    {
+        return this._hoveredMarker;
+    },
+    
+    set hoveredMarker(hoveredMarker)
+    {
+        this._hoveredMarker = hoveredMarker;
+    },
+
</ins><span class="cx">     highlightLastHoveredRange: function()
</span><span class="cx">     {
</span><span class="cx">         if (this._candidate)
</span><span class="lines">@@ -176,13 +189,6 @@
</span><span class="cx">         window.removeEventListener(&quot;mousemove&quot;, this, true);
</span><span class="cx">     },
</span><span class="cx"> 
</span><del>-    boundsForRange: function(range)
-    {
-        var firstCharCoords = this._codeMirror.cursorCoords(range.start);
-        var lastCharCoords = this._codeMirror.cursorCoords(range.end);
-        return new WebInspector.Rect(firstCharCoords.left, firstCharCoords.top, lastCharCoords.right - firstCharCoords.left, firstCharCoords.bottom - firstCharCoords.top);
-    },
-
</del><span class="cx">     // Private
</span><span class="cx"> 
</span><span class="cx">     _startTracking: function()
</span><span class="lines">@@ -298,6 +304,12 @@
</span><span class="cx">         var token = this._codeMirror.getTokenAt(position);
</span><span class="cx"> 
</span><span class="cx">         if (!token || !token.type || !token.string) {
</span><ins>+            if (this._hoveredMarker &amp;&amp; this._delegate &amp;&amp; typeof this._delegate.tokenTrackingControllerMouseOutOfHoveredMarker === &quot;function&quot;) {
+                var markers = this._codeMirror.findMarksAt(position);
+                if (!markers.contains(this._hoveredMarker))
+                    this._delegate.tokenTrackingControllerMouseOutOfHoveredMarker(this, this._hoveredMarker);
+            }
+
</ins><span class="cx">             this._resetTrackingStates();
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="lines">@@ -380,6 +392,9 @@
</span><span class="cx">         case WebInspector.CodeMirrorTokenTrackingController.Mode.JavaScriptExpression:
</span><span class="cx">             this._candidate = this._processJavaScriptExpression();
</span><span class="cx">             break;
</span><ins>+        case WebInspector.CodeMirrorTokenTrackingController.Mode.MarkedTokens:
+            this._candidate = this._processMarkedToken();
+            break;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (!this._candidate)
</span><span class="lines">@@ -478,6 +493,11 @@
</span><span class="cx">         };
</span><span class="cx">     },
</span><span class="cx"> 
</span><ins>+    _processMarkedToken: function()
+    {
+        return this._processNonSymbolToken();
+    },
+
</ins><span class="cx">     _resetTrackingStates: function()
</span><span class="cx">     {
</span><span class="cx">         clearTimeout(this._tokenHoverTimer);
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceColorjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Color.js (160482 => 160483)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Color.js        2013-12-12 10:10:36 UTC (rev 160482)
+++ trunk/Source/WebInspectorUI/UserInterface/Color.js        2013-12-12 10:17:20 UTC (rev 160483)
</span><span class="lines">@@ -34,6 +34,10 @@
</span><span class="cx">         this._hsla = components;
</span><span class="cx">     else
</span><span class="cx">         this._rgba = components;
</span><ins>+
+    this.valid = !components.some(function(component) {
+        return isNaN(component);
+    });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> WebInspector.Color.Format = {
</span><span class="lines">@@ -211,6 +215,21 @@
</span><span class="cx">         return this._hsla;
</span><span class="cx">     },
</span><span class="cx"> 
</span><ins>+    copy: function()
+    {
+        switch (this.format) {
+        case WebInspector.Color.Format.RGB:
+        case WebInspector.Color.Format.HEX:
+        case WebInspector.Color.Format.ShortHEX:
+        case WebInspector.Color.Format.Nickname:
+        case WebInspector.Color.Format.RGBA:
+            return new WebInspector.Color(this.format, this.rgba);
+        case WebInspector.Color.Format.HSL:
+        case WebInspector.Color.Format.HSLA:
+            return new WebInspector.Color(this.format, this.hsla);
+        }
+    },
+
</ins><span class="cx">     toString: function(format)
</span><span class="cx">     {
</span><span class="cx">         if (!format)
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceHoverMenujs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/HoverMenu.js (160482 => 160483)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/HoverMenu.js        2013-12-12 10:10:36 UTC (rev 160482)
+++ trunk/Source/WebInspectorUI/UserInterface/HoverMenu.js        2013-12-12 10:17:20 UTC (rev 160483)
</span><span class="lines">@@ -101,7 +101,7 @@
</span><span class="cx"> 
</span><span class="cx">     _handleClickEvent: function(event)
</span><span class="cx">     {
</span><del>-        if (this.delegate &amp;&amp; typeof this.delegate.hoverMenuWasActivated === &quot;function&quot;)
-            this.delegate.hoverMenuWasActivated(this);
</del><ins>+        if (this.delegate &amp;&amp; typeof this.delegate.hoverMenuButtonWasPressed === &quot;function&quot;)
+            this.delegate.hoverMenuButtonWasPressed(this);
</ins><span class="cx">     }
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceImagesColorIconpng"></a>
<div class="binary"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Images/ColorIcon.png</h4>
<pre class="diff"><span>
<span class="cx">(Binary files differ)
</span></span></pre></div>
<span class="cx">Property changes on: trunk/Source/WebInspectorUI/UserInterface/Images/ColorIcon.png
</span><span class="cx">___________________________________________________________________
</span><a id="svnmimetype"></a>
<div class="addfile"><h4>Added: svn:mime-type</h4></div>
<a id="trunkSourceWebInspectorUIUserInterfaceImagesColorIcon2xpng"></a>
<div class="binary"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Images/ColorIcon@2x.png</h4>
<pre class="diff"><span>
<span class="cx">(Binary files differ)
</span></span></pre></div>
<span class="cx">Property changes on: trunk/Source/WebInspectorUI/UserInterface/Images/ColorIcon@2x.png
</span><span class="cx">___________________________________________________________________
</span><a id="svnmimetype"></a>
<div class="addfile"><h4>Added: svn:mime-type</h4></div>
<a id="trunkSourceWebInspectorUIUserInterfaceMainhtml"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Main.html (160482 => 160483)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Main.html        2013-12-12 10:10:36 UTC (rev 160482)
+++ trunk/Source/WebInspectorUI/UserInterface/Main.html        2013-12-12 10:17:20 UTC (rev 160483)
</span><span class="lines">@@ -412,6 +412,7 @@
</span><span class="cx">     &lt;script src=&quot;GoToLineDialog.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;ContentFlowDOMTreeContentView.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;HoverMenu.js&quot;&gt;&lt;/script&gt;
</span><ins>+    &lt;script src=&quot;CodeMirrorColorEditingController.js&quot;&gt;&lt;/script&gt;
</ins><span class="cx">     &lt;script src=&quot;Main.js&quot;&gt;&lt;/script&gt;
</span><span class="cx"> 
</span><span class="cx">     &lt;script&gt;
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceSourceCodeTextEditorcss"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/SourceCodeTextEditor.css (160482 => 160483)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/SourceCodeTextEditor.css        2013-12-12 10:10:36 UTC (rev 160482)
+++ trunk/Source/WebInspectorUI/UserInterface/SourceCodeTextEditor.css        2013-12-12 10:17:20 UTC (rev 160483)
</span><span class="lines">@@ -61,3 +61,16 @@
</span><span class="cx">     padding-left: 10px;
</span><span class="cx">     padding-right: 10px;
</span><span class="cx"> }
</span><ins>+
+/* Custom styling for the hover menu attached to color tokens */
+
+.hover-menu.color {
+    padding-right: 15px;
+}
+
+.hover-menu.color &gt; img {
+    width: 16px;
+    height: 16px;
+    -webkit-transform: translateX(14px);
+    content: -webkit-image-set(url(Images/ColorIcon.png) 1x, url(Images/ColorIcon@2x.png) 2x);
+}
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceSourceCodeTextEditorjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/SourceCodeTextEditor.js (160482 => 160483)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/SourceCodeTextEditor.js        2013-12-12 10:10:36 UTC (rev 160482)
+++ trunk/Source/WebInspectorUI/UserInterface/SourceCodeTextEditor.js        2013-12-12 10:17:20 UTC (rev 160483)
</span><span class="lines">@@ -32,12 +32,12 @@
</span><span class="cx">     this._issuesLineNumberMap = {};
</span><span class="cx">     this._contentPopulated = false;
</span><span class="cx">     this._invalidLineNumbers = {0: true};
</span><ins>+    this._ignoreContentDidChange = 0;
</ins><span class="cx"> 
</span><span class="cx">     WebInspector.TextEditor.call(this, null, null, this);
</span><span class="cx"> 
</span><span class="cx">     // FIXME: Currently this just jumps between resources and related source map resources. It doesn't &quot;jump to symbol&quot; yet.
</span><del>-    this._jumpToSymbolTrackingModeEnabled = false;
-    this._disableJumpToSymbolTrackingModeSettings();
</del><ins>+    this._updateTokenTrackingControllerState();
</ins><span class="cx"> 
</span><span class="cx">     this.element.classList.add(WebInspector.SourceCodeTextEditor.StyleClassName);
</span><span class="cx"> 
</span><span class="lines">@@ -61,7 +61,7 @@
</span><span class="cx">     WebInspector.issueManager.addEventListener(WebInspector.IssueManager.Event.IssueWasAdded, this._issueWasAdded, this);
</span><span class="cx"> 
</span><span class="cx">     if (this._sourceCode instanceof WebInspector.SourceMapResource || this._sourceCode.sourceMaps.length &gt; 0)
</span><del>-        WebInspector.notifications.addEventListener(WebInspector.Notification.GlobalModifierKeysDidChange, this._updateJumpToSymbolTrackingMode, this);
</del><ins>+        WebInspector.notifications.addEventListener(WebInspector.Notification.GlobalModifierKeysDidChange, this._updateTokenTrackingControllerState, this);
</ins><span class="cx">     else
</span><span class="cx">         this._sourceCode.addEventListener(WebInspector.SourceCode.Event.SourceMapAdded, this._sourceCodeSourceMapAdded, this);
</span><span class="cx"> 
</span><span class="lines">@@ -127,7 +127,7 @@
</span><span class="cx"> 
</span><span class="cx">         WebInspector.issueManager.removeEventListener(WebInspector.IssueManager.Event.IssueWasAdded, this._issueWasAdded, this);
</span><span class="cx"> 
</span><del>-        WebInspector.notifications.removeEventListener(WebInspector.Notification.GlobalModifierKeysDidChange, this._updateJumpToSymbolTrackingMode, this);
</del><ins>+        WebInspector.notifications.removeEventListener(WebInspector.Notification.GlobalModifierKeysDidChange, this._updateTokenTrackingControllerState, this);
</ins><span class="cx">         this._sourceCode.removeEventListener(WebInspector.SourceCode.Event.SourceMapAdded, this._sourceCodeSourceMapAdded, this);
</span><span class="cx">     },
</span><span class="cx"> 
</span><span class="lines">@@ -217,6 +217,32 @@
</span><span class="cx">         this.focus();
</span><span class="cx">     },
</span><span class="cx"> 
</span><ins>+    contentDidChange: function(replacedRanges, newRanges)
+    {
+        WebInspector.TextEditor.prototype.contentDidChange.call(this, replacedRanges, newRanges);
+
+        if (this._ignoreContentDidChange &gt; 0)
+            return;
+
+        // Gather all lines containing new text.
+        var lines = new Set;
+        for (var range of newRanges) {
+            // If the range is on a single line, only add the line if the range is not empty.
+            if (range.startLine === range.endLine) {
+                if (range.endColumn &gt; range.startColumn)
+                    lines.add(range.startLine);
+            } else {
+                // Only add the last line if the range has characters on this line.
+                for (var line = range.startLine; line &lt; range.endLine || range.endColumn &gt; 0; ++line)
+                    lines.add(line);
+            }
+        }
+
+        // Consider all new lines for new color markers.
+        for (var line of lines)
+            this._updateColorMarkers(line);
+    },
+
</ins><span class="cx">     // Private
</span><span class="cx"> 
</span><span class="cx">     _unformattedLineInfoForEditorLineInfo: function(lineInfo)
</span><span class="lines">@@ -332,7 +358,8 @@
</span><span class="cx">             this._addIssue(issue);
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        this._updateJumpToSymbolTrackingMode();
</del><ins>+        this._updateTokenTrackingControllerState();
+        this._updateColorMarkers();
</ins><span class="cx">     },
</span><span class="cx"> 
</span><span class="cx">     _populateWithContent: function(content)
</span><span class="lines">@@ -931,70 +958,68 @@
</span><span class="cx">         }
</span><span class="cx">     },
</span><span class="cx"> 
</span><del>-    _updateTokenTrackingControllerEnabled: function()
-    {
-        this.tokenTrackingController.enabled = this._jumpToSymbolTrackingModeEnabled || WebInspector.debuggerManager.activeCallFrame;
-    },
-
</del><span class="cx">     _debuggerDidPause: function(event)
</span><span class="cx">     {
</span><del>-        this._updateTokenTrackingControllerEnabled();
</del><ins>+        this._updateTokenTrackingControllerState();
</ins><span class="cx">     },
</span><span class="cx"> 
</span><span class="cx">     _debuggerDidResume: function(event)
</span><span class="cx">     {
</span><del>-        this._updateTokenTrackingControllerEnabled();
</del><ins>+        this._updateTokenTrackingControllerState();
</ins><span class="cx">         this._dismissPopover();
</span><span class="cx">     },
</span><span class="cx"> 
</span><span class="cx">     _sourceCodeSourceMapAdded: function(event)
</span><span class="cx">     {
</span><del>-        WebInspector.notifications.addEventListener(WebInspector.Notification.GlobalModifierKeysDidChange, this._updateJumpToSymbolTrackingMode, this);
</del><ins>+        WebInspector.notifications.addEventListener(WebInspector.Notification.GlobalModifierKeysDidChange, this._updateTokenTrackingControllerState, this);
</ins><span class="cx">         this._sourceCode.removeEventListener(WebInspector.SourceCode.Event.SourceMapAdded, this._sourceCodeSourceMapAdded, this);
</span><span class="cx"> 
</span><del>-        this._updateJumpToSymbolTrackingMode();
</del><ins>+        this._updateTokenTrackingControllerState();
</ins><span class="cx">     },
</span><span class="cx"> 
</span><del>-    _updateJumpToSymbolTrackingMode: function()
</del><ins>+    _updateTokenTrackingControllerState: function()
</ins><span class="cx">     {
</span><del>-        var oldJumpToSymbolTrackingModeEnabled = this._jumpToSymbolTrackingModeEnabled;
</del><ins>+        var mode = WebInspector.CodeMirrorTokenTrackingController.Mode.None;
+        if (WebInspector.debuggerManager.paused)
+            mode = WebInspector.CodeMirrorTokenTrackingController.Mode.JavaScriptExpression;
+        else if (this._hasColorMarkers())
+            mode = WebInspector.CodeMirrorTokenTrackingController.Mode.MarkedTokens;
+        else if ((this._sourceCode instanceof WebInspector.SourceMapResource || this._sourceCode.sourceMaps.length !== 0) &amp;&amp; WebInspector.modifierKeys.metaKey &amp;&amp; !WebInspector.modifierKeys.altKey &amp;&amp; !WebInspector.modifierKeys.shiftKey)
+            mode = WebInspector.CodeMirrorTokenTrackingController.Mode.NonSymbolTokens;
</ins><span class="cx"> 
</span><del>-        if (!(this._sourceCode instanceof WebInspector.SourceMapResource) &amp;&amp; this._sourceCode.sourceMaps.length === 0)
-            this._jumpToSymbolTrackingModeEnabled = false;
-        else
-            this._jumpToSymbolTrackingModeEnabled = WebInspector.modifierKeys.metaKey &amp;&amp; !WebInspector.modifierKeys.altKey &amp;&amp; !WebInspector.modifierKeys.shiftKey;
</del><ins>+        this.tokenTrackingController.enabled = mode !== WebInspector.CodeMirrorTokenTrackingController.Mode.None;
</ins><span class="cx"> 
</span><del>-        if (oldJumpToSymbolTrackingModeEnabled !== this._jumpToSymbolTrackingModeEnabled) {
-            if (this._jumpToSymbolTrackingModeEnabled) {
-                this._enableJumpToSymbolTrackingModeSettings();
-                this.tokenTrackingController.highlightLastHoveredRange();
-            } else {
-                this._disableJumpToSymbolTrackingModeSettings();
-                this.tokenTrackingController.removeHighlightedRange();
-            }
</del><ins>+        if (mode === this.tokenTrackingController.mode)
+            return;
+
+        switch (mode) {
+        case WebInspector.CodeMirrorTokenTrackingController.Mode.MarkedTokens:
+            this.tokenTrackingController.mouseOverDelayDuration = 0;
+            this.tokenTrackingController.mouseOutReleaseDelayDuration = 0;
+            break;
+        case WebInspector.CodeMirrorTokenTrackingController.Mode.NonSymbolTokens:
+            this.tokenTrackingController.mouseOverDelayDuration = 0;
+            this.tokenTrackingController.mouseOutReleaseDelayDuration = 0;
+            this.tokenTrackingController.classNameForHighlightedRange = WebInspector.CodeMirrorTokenTrackingController.JumpToSymbolHighlightStyleClassName;
+            this._dismissPopover();
+            break;
+        case WebInspector.CodeMirrorTokenTrackingController.Mode.JavaScriptExpression:
+            this.tokenTrackingController.mouseOverDelayDuration = WebInspector.SourceCodeTextEditor.DurationToMouseOverTokenToMakeHoveredToken;
+            this.tokenTrackingController.mouseOutReleaseDelayDuration = WebInspector.SourceCodeTextEditor.DurationToMouseOutOfHoveredTokenToRelease;
+            this.tokenTrackingController.classNameForHighlightedRange = WebInspector.SourceCodeTextEditor.HoveredExpressionHighlightStyleClassName;
+            break;
</ins><span class="cx">         }
</span><del>-    },
</del><span class="cx"> 
</span><del>-    _enableJumpToSymbolTrackingModeSettings: function()
-    {
-        this.tokenTrackingController.classNameForHighlightedRange = WebInspector.CodeMirrorTokenTrackingController.JumpToSymbolHighlightStyleClassName;
-        this.tokenTrackingController.mouseOverDelayDuration = 0;
-        this.tokenTrackingController.mouseOutReleaseDelayDuration = 0;
-
-        this.tokenTrackingController.mode = WebInspector.CodeMirrorTokenTrackingController.Mode.NonSymbolTokens;
-        this._updateTokenTrackingControllerEnabled();
-
-        this._dismissPopover();
</del><ins>+        this.tokenTrackingController.mode = mode;
</ins><span class="cx">     },
</span><span class="cx"> 
</span><del>-    _disableJumpToSymbolTrackingModeSettings: function()
</del><ins>+    _hasColorMarkers: function()
</ins><span class="cx">     {
</span><del>-        this.tokenTrackingController.classNameForHighlightedRange = WebInspector.SourceCodeTextEditor.HoveredExpressionHighlightStyleClassName;
-        this.tokenTrackingController.mouseOverDelayDuration = WebInspector.SourceCodeTextEditor.DurationToMouseOverTokenToMakeHoveredToken;
-        this.tokenTrackingController.mouseOutReleaseDelayDuration = WebInspector.SourceCodeTextEditor.DurationToMouseOutOfHoveredTokenToRelease;
-
-        this.tokenTrackingController.mode = WebInspector.CodeMirrorTokenTrackingController.Mode.JavaScriptExpression;
-        this._updateTokenTrackingControllerEnabled();
</del><ins>+        for (var marker of this.markers) {
+            if (marker.__markedColor)
+                return true;
+        }
+        return false;
</ins><span class="cx">     },
</span><span class="cx"> 
</span><span class="cx">     // CodeMirrorTokenTrackingController Delegate
</span><span class="lines">@@ -1018,29 +1043,48 @@
</span><span class="cx"> 
</span><span class="cx">     tokenTrackingControllerHighlightedRangeWasClicked: function(tokenTrackingController)
</span><span class="cx">     {
</span><del>-        if (this._jumpToSymbolTrackingModeEnabled) {
-            // Links are handled by TextEditor.
-            if (/\blink\b/.test(this.tokenTrackingController.candidate.hoveredToken.type))
-                return;
</del><ins>+        if (this.tokenTrackingController.mode !== WebInspector.CodeMirrorTokenTrackingController.Mode.NonSymbolTokens)
+            return;
</ins><span class="cx"> 
</span><del>-            var sourceCodeLocation = this._sourceCodeLocationForEditorPosition(this.tokenTrackingController.candidate.hoveredTokenRange.start);
-            if (this.sourceCode instanceof WebInspector.SourceMapResource)
-                WebInspector.resourceSidebarPanel.showOriginalOrFormattedSourceCodeLocation(sourceCodeLocation);
-            else
-                WebInspector.resourceSidebarPanel.showSourceCodeLocation(sourceCodeLocation);
-        }
</del><ins>+        // Links are handled by TextEditor.
+        if (/\blink\b/.test(this.tokenTrackingController.candidate.hoveredToken.type))
+            return;
+
+        var sourceCodeLocation = this._sourceCodeLocationForEditorPosition(this.tokenTrackingController.candidate.hoveredTokenRange.start);
+        if (this.sourceCode instanceof WebInspector.SourceMapResource)
+            WebInspector.resourceSidebarPanel.showOriginalOrFormattedSourceCodeLocation(sourceCodeLocation);
+        else
+            WebInspector.resourceSidebarPanel.showSourceCodeLocation(sourceCodeLocation);
</ins><span class="cx">     },
</span><span class="cx"> 
</span><span class="cx">     tokenTrackingControllerNewHighlightCandidate: function(tokenTrackingController, candidate)
</span><span class="cx">     {
</span><del>-        if (this._jumpToSymbolTrackingModeEnabled) {
</del><ins>+        if (this.tokenTrackingController.mode === WebInspector.CodeMirrorTokenTrackingController.Mode.NonSymbolTokens) {
</ins><span class="cx">             this.tokenTrackingController.highlightRange(candidate.hoveredTokenRange);
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (!WebInspector.debuggerManager.activeCallFrame)
</del><ins>+        if (this.tokenTrackingController.mode === WebInspector.CodeMirrorTokenTrackingController.Mode.JavaScriptExpression) {
+            this._tokenTrackingControllerHighlightedJavaScriptExpression(candidate);
</ins><span class="cx">             return;
</span><ins>+        }
</ins><span class="cx"> 
</span><ins>+        if (this.tokenTrackingController.mode === WebInspector.CodeMirrorTokenTrackingController.Mode.MarkedTokens) {
+            var markers = this.findMarkersAtPosition(candidate.hoveredTokenRange.start);
+            if (markers.length &gt; 0)
+                this._tokenTrackingControllerHighlightedMarkedExpression(candidate, markers);
+            else
+                this._dismissCodeMirrorColorEditingController();
+        }
+    },
+
+    tokenTrackingControllerMouseOutOfHoveredMarker: function(tokenTrackingController, hoveredMarker)
+    {
+        this._dismissCodeMirrorColorEditingController();
+    },
+
+    _tokenTrackingControllerHighlightedJavaScriptExpression: function(candidate)
+    {
</ins><span class="cx">         console.assert(candidate.expression);
</span><span class="cx"> 
</span><span class="cx">         function populate(error, result, wasThrown)
</span><span class="lines">@@ -1085,7 +1129,7 @@
</span><span class="cx">         if (!candidate)
</span><span class="cx">             return;
</span><span class="cx"> 
</span><del>-        var bounds = this.tokenTrackingController.boundsForRange(candidate.hoveredTokenRange);
</del><ins>+        var bounds = this.boundsForRange(candidate.hoveredTokenRange);
</ins><span class="cx">         if (!bounds)
</span><span class="cx">             return;
</span><span class="cx"> 
</span><span class="lines">@@ -1241,6 +1285,82 @@
</span><span class="cx">     _popoverMouseout: function(event)
</span><span class="cx">     {
</span><span class="cx">         this._mouseIsOverPopover = this._popover.element.contains(event.relatedTarget);
</span><ins>+    },
+
+    _updateColorMarkers: function(lineNumber)
+    {
+        this.createColorMarkers(lineNumber);
+
+        this._updateTokenTrackingControllerState();
+    },
+    
+    _tokenTrackingControllerHighlightedMarkedExpression: function(candidate, markers)
+    {
+        var colorMarker;
+        for (var marker of markers) {
+            if (marker.__markedColor) {
+                colorMarker = marker;
+                break;
+            }
+        }
+
+        if (!colorMarker) {
+            this.tokenTrackingController.hoveredMarker = null;
+            return;
+        }
+
+        if (this.tokenTrackingController.hoveredMarker === colorMarker)
+            return;
+
+        this._dismissCodeMirrorColorEditingController();
+
+        this.tokenTrackingController.hoveredMarker = colorMarker;
+
+        this._colorEditingController = this.colorEditingControllerForMarker(colorMarker);
+
+        var color = this._colorEditingController.color;
+        if (!color || !color.valid) {
+            colorMarker.clear();
+            delete this._colorEditingController;
+            return;
+        }
+
+        this._colorEditingController.delegate = this;
+        this._colorEditingController.presentHoverMenu();
+    },
+
+    _dismissCodeMirrorColorEditingController: function()
+    {
+        if (this._colorEditingController)
+            this._colorEditingController.dismissHoverMenu();
+        
+        this.tokenTrackingController.hoveredMarker = null;
+        delete this._colorEditingController;
+    },
+
+    // CodeMirrorColorEditingController Delegate
+    
+    colorEditingControllerDidStartEditing: function(colorEditingController)
+    {
+        // We can pause the token tracking controller during editing, it will be reset
+        // to the expected state by calling _updateColorMarkers() in the
+        // colorEditingControllerDidFinishEditing delegate.
+        this.tokenTrackingController.enabled = false;
+
+        // We clear the marker since we'll reset it after editing.
+        colorEditingController.marker.clear();
+        
+        // We ignore content changes made as a result of color editing.
+        this._ignoreContentDidChange++;
+    },
+    
+    colorEditingControllerDidFinishEditing: function(colorEditingController)
+    {
+        this._updateColorMarkers(colorEditingController.range.from.line);
+
+        this._ignoreContentDidChange--;
+
+        delete this._colorEditingController;
</ins><span class="cx">     }
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceTextEditorjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/TextEditor.js (160482 => 160483)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/TextEditor.js        2013-12-12 10:10:36 UTC (rev 160482)
+++ trunk/Source/WebInspectorUI/UserInterface/TextEditor.js        2013-12-12 10:17:20 UTC (rev 160483)
</span><span class="lines">@@ -591,6 +591,37 @@
</span><span class="cx">         this._codeMirror.focus();
</span><span class="cx">     },
</span><span class="cx"> 
</span><ins>+    contentDidChange: function(replacedRanges, newRanges)
+    {
+        // Implemented by subclasses.
+    },
+
+    boundsForRange: function(range)
+    {
+        return this._codeMirror.boundsForRange(range);
+    },
+
+    get markers()
+    {
+        // FIXME: we should not return CodeMirror TextMarker objects but rather wrappers.
+        return this._codeMirror.getAllMarks();
+    },
+
+    findMarkersAtPosition: function(position)
+    {
+        return this._codeMirror.findMarksAt(position);
+    },
+
+    createColorMarkers: function(lineNumber)
+    {
+        return this._codeMirror.createColorMarkers(lineNumber);
+    },
+
+    colorEditingControllerForMarker: function(colorMarker)
+    {
+        return new WebInspector.CodeMirrorColorEditingController(this._codeMirror, colorMarker);
+    },
+
</ins><span class="cx">     // Private
</span><span class="cx"> 
</span><span class="cx">     _contentChanged: function(codeMirror, change)
</span><span class="lines">@@ -598,6 +629,25 @@
</span><span class="cx">         if (this._ignoreCodeMirrorContentDidChangeEvent &gt; 0)
</span><span class="cx">             return;
</span><span class="cx"> 
</span><ins>+        var replacedRanges = [];
+        var newRanges = [];
+        while (change) {
+            replacedRanges.push(new WebInspector.TextRange(
+                change.from.line,
+                change.from.ch,
+                change.to.line,
+                change.to.ch
+            ));
+            newRanges.push(new WebInspector.TextRange(
+                change.from.line,
+                change.from.ch,
+                change.from.line + change.text.length - 1,
+                change.text.length === 1 ? change.from.ch + change.text[0].length : change.text.lastValue.length
+            ));
+            change = change.next;
+        }
+        this.contentDidChange(replacedRanges, newRanges);
+
</ins><span class="cx">         if (this._formatted) {
</span><span class="cx">             this._formatterSourceMap = null;
</span><span class="cx">             this._formatted = false;
</span></span></pre>
</div>
</div>

</body>
</html>