2 * Copyright (C) 2013 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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
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.
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
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * @extends {WebInspector.InplaceEditor}
35 WebInspector
.CodeMirrorUtils = function()
37 WebInspector
.InplaceEditor
.call(this);
41 * @param {!WebInspector.TextRange} range
42 * @return {!{start: !CodeMirror.Pos, end: !CodeMirror.Pos}}
44 WebInspector
.CodeMirrorUtils
.toPos = function(range
)
47 start
: new CodeMirror
.Pos(range
.startLine
, range
.startColumn
),
48 end
: new CodeMirror
.Pos(range
.endLine
, range
.endColumn
)
53 * @param {!CodeMirror.Pos} start
54 * @param {!CodeMirror.Pos} end
55 * @return {!WebInspector.TextRange}
57 WebInspector
.CodeMirrorUtils
.toRange = function(start
, end
)
59 return new WebInspector
.TextRange(start
.line
, start
.ch
, end
.line
, end
.ch
);
63 * @param {!CodeMirror.ChangeObject} changeObject
64 * @return {{oldRange: !WebInspector.TextRange, newRange: !WebInspector.TextRange}}
66 WebInspector
.CodeMirrorUtils
.changeObjectToEditOperation = function(changeObject
)
68 var oldRange
= WebInspector
.CodeMirrorUtils
.toRange(changeObject
.from, changeObject
.to
);
69 var newRange
= oldRange
.clone();
70 var linesAdded
= changeObject
.text
.length
;
71 if (linesAdded
=== 0) {
72 newRange
.endLine
= newRange
.startLine
;
73 newRange
.endColumn
= newRange
.startColumn
;
74 } else if (linesAdded
=== 1) {
75 newRange
.endLine
= newRange
.startLine
;
76 newRange
.endColumn
= newRange
.startColumn
+ changeObject
.text
[0].length
;
78 newRange
.endLine
= newRange
.startLine
+ linesAdded
- 1;
79 newRange
.endColumn
= changeObject
.text
[linesAdded
- 1].length
;
88 * @param {!CodeMirror} codeMirror
89 * @param {number} linesCount
90 * @return {!Array.<string>}
92 WebInspector
.CodeMirrorUtils
.pullLines = function(codeMirror
, linesCount
)
95 codeMirror
.eachLine(0, linesCount
, onLineHandle
);
99 * @param {!{text: string}} lineHandle
101 function onLineHandle(lineHandle
)
103 lines
.push(lineHandle
.text
);
107 WebInspector
.CodeMirrorUtils
.prototype = {
112 editorContent: function(editingContext
) {
113 return editingContext
.codeMirror
.getValue();
119 _consumeCopy: function(e
)
124 setUpEditor: function(editingContext
)
126 var element
= editingContext
.element
;
127 var config
= editingContext
.config
;
128 editingContext
.cssLoadView
= new WebInspector
.CodeMirrorCSSLoadView();
129 editingContext
.cssLoadView
.show(element
);
130 WebInspector
.setCurrentFocusElement(element
);
131 element
.addEventListener("copy", this._consumeCopy
, false);
132 var codeMirror
= new window
.CodeMirror(element
, {
134 lineWrapping
: config
.lineWrapping
,
135 smartIndent
: config
.smartIndent
,
138 value
: config
.initialValue
140 codeMirror
.getWrapperElement().classList
.add("source-code");
141 codeMirror
.on("cursorActivity", function(cm
) {
142 cm
.display
.cursorDiv
.scrollIntoViewIfNeeded(false);
144 editingContext
.codeMirror
= codeMirror
;
147 closeEditor: function(editingContext
)
149 editingContext
.element
.removeEventListener("copy", this._consumeCopy
, false);
150 editingContext
.cssLoadView
.detach();
153 cancelEditing: function(editingContext
)
155 editingContext
.codeMirror
.setValue(editingContext
.oldText
);
158 augmentEditingHandle: function(editingContext
, handle
)
160 function setWidth(editingContext
, width
)
163 var codeMirror
= editingContext
.codeMirror
;
164 codeMirror
.getWrapperElement().style
.width
= (width
- codeMirror
.getWrapperElement().offsetLeft
- padding
) + "px";
165 codeMirror
.refresh();
168 handle
.codeMirror
= editingContext
.codeMirror
;
169 handle
.setWidth
= setWidth
.bind(null, editingContext
);
172 __proto__
: WebInspector
.InplaceEditor
.prototype
177 * @implements {WebInspector.TokenizerFactory}
179 WebInspector
.CodeMirrorUtils
.TokenizerFactory = function() { }
181 WebInspector
.CodeMirrorUtils
.TokenizerFactory
.prototype = {
184 * @param {string} mimeType
185 * @return {function(string, function(string, ?string, number, number))}
187 createTokenizer: function(mimeType
)
189 var mode
= CodeMirror
.getMode({indentUnit
: 2}, mimeType
);
190 var state
= CodeMirror
.startState(mode
);
191 function tokenize(line
, callback
)
193 var stream
= new CodeMirror
.StringStream(line
);
194 while (!stream
.eol()) {
195 var style
= mode
.token(stream
, state
);
196 var value
= stream
.current();
197 callback(value
, style
, stream
.start
, stream
.start
+ value
.length
);
198 stream
.start
= stream
.pos
;
206 * This bogus view is needed to load/unload CodeMirror-related CSS on demand.
209 * @extends {WebInspector.VBox}
211 WebInspector
.CodeMirrorCSSLoadView = function()
213 WebInspector
.VBox
.call(this);
214 this.element
.classList
.add("hidden");
215 this.registerRequiredCSS("cm/codemirror.css");
216 this.registerRequiredCSS("source_frame/cmdevtools.css");
217 this.element
.appendChild(WebInspector
.CodeMirrorUtils
.createThemeStyle());
220 WebInspector
.CodeMirrorCSSLoadView
.prototype = {
221 __proto__
: WebInspector
.VBox
.prototype
228 WebInspector
.CodeMirrorUtils
.createThemeStyle = function()
230 var backgroundColor
= InspectorFrontendHost
.getSelectionBackgroundColor();
231 var backgroundColorRule
= backgroundColor
? ".CodeMirror .CodeMirror-selected { background-color: " + backgroundColor
+ ";}" : "";
232 var foregroundColor
= InspectorFrontendHost
.getSelectionForegroundColor();
233 var foregroundColorRule
= foregroundColor
? ".CodeMirror .CodeMirror-selectedtext:not(.CodeMirror-persist-highlight) { color: " + foregroundColor
+ "!important;}" : "";
234 var style
= createElement("style");
235 if (foregroundColorRule
|| backgroundColorRule
)
236 style
.textContent
= backgroundColorRule
+ foregroundColorRule
;