bzr branch
http://gegoxaren.bato24.eu/bzr/lenasys/trunk
15.1.1
by galaxyAbstractor
Started implementation of a new codeviewer using Ace |
1 |
/* ***** BEGIN LICENSE BLOCK *****
|
2 |
* Distributed under the BSD license:
|
|
3 |
*
|
|
4 |
* Copyright (c) 2010, Ajax.org B.V.
|
|
5 |
* All rights reserved.
|
|
6 |
*
|
|
7 |
* Redistribution and use in source and binary forms, with or without
|
|
8 |
* modification, are permitted provided that the following conditions are met:
|
|
9 |
* * Redistributions of source code must retain the above copyright
|
|
10 |
* notice, this list of conditions and the following disclaimer.
|
|
11 |
* * Redistributions in binary form must reproduce the above copyright
|
|
12 |
* notice, this list of conditions and the following disclaimer in the
|
|
13 |
* documentation and/or other materials provided with the distribution.
|
|
14 |
* * Neither the name of Ajax.org B.V. nor the
|
|
15 |
* names of its contributors may be used to endorse or promote products
|
|
16 |
* derived from this software without specific prior written permission.
|
|
17 |
*
|
|
18 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
19 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
20 |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
21 |
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
|
22 |
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
23 |
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
24 |
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
25 |
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
26 |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
27 |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
28 |
*
|
|
29 |
* ***** END LICENSE BLOCK ***** */
|
|
30 |
||
31 |
define('ace/ext/searchbox', ['require', 'exports', 'module' , 'ace/lib/dom', 'ace/lib/lang', 'ace/lib/event', 'ace/keyboard/hash_handler', 'ace/lib/keys'], function(require, exports, module) { |
|
32 |
||
33 |
||
34 |
var dom = require("../lib/dom"); |
|
35 |
var lang = require("../lib/lang"); |
|
36 |
var event = require("../lib/event"); |
|
37 |
var searchboxCss = "\ |
|
38 |
/* ------------------------------------------------------------------------------------------\
|
|
39 |
* Editor Search Form\
|
|
40 |
* --------------------------------------------------------------------------------------- */\
|
|
41 |
.ace_search {\
|
|
42 |
background-color: #ddd;\
|
|
43 |
border: 1px solid #cbcbcb;\
|
|
44 |
border-top: 0 none;\
|
|
45 |
max-width: 297px;\
|
|
46 |
overflow: hidden;\
|
|
47 |
margin: 0;\
|
|
48 |
padding: 4px;\
|
|
49 |
padding-right: 6px;\
|
|
50 |
padding-bottom: 0;\
|
|
51 |
position: absolute;\
|
|
52 |
top: 0px;\
|
|
53 |
z-index: 99;\
|
|
54 |
}\
|
|
55 |
.ace_search.left {\
|
|
56 |
border-left: 0 none;\
|
|
57 |
border-radius: 0px 0px 5px 0px;\
|
|
58 |
left: 0;\
|
|
59 |
}\
|
|
60 |
.ace_search.right {\
|
|
61 |
border-radius: 0px 0px 0px 5px;\
|
|
62 |
border-right: 0 none;\
|
|
63 |
right: 0;\
|
|
64 |
}\
|
|
65 |
.ace_search_form, .ace_replace_form {\
|
|
66 |
border-radius: 3px;\
|
|
67 |
border: 1px solid #cbcbcb;\
|
|
68 |
float: left;\
|
|
69 |
margin-bottom: 4px;\
|
|
70 |
overflow: hidden;\
|
|
71 |
}\
|
|
72 |
.ace_search_field {\
|
|
73 |
background-color: white;\
|
|
74 |
border-right: 1px solid #cbcbcb;\
|
|
75 |
border: 0 none;\
|
|
76 |
-webkit-box-sizing: border-box;\
|
|
77 |
-moz-box-sizing: border-box;\
|
|
78 |
box-sizing: border-box;\
|
|
79 |
display: block;\
|
|
80 |
float: left;\
|
|
81 |
height: 22px;\
|
|
82 |
outline: 0;\
|
|
83 |
padding: 0 7px;\
|
|
84 |
width: 214px;\
|
|
85 |
margin: 0;\
|
|
86 |
}\
|
|
87 |
.ace_searchbtn,\
|
|
88 |
.ace_replacebtn {\
|
|
89 |
background: #fff;\
|
|
90 |
border: 0 none;\
|
|
91 |
border-left: 1px solid #dcdcdc;\
|
|
92 |
cursor: pointer;\
|
|
93 |
display: block;\
|
|
94 |
float: left;\
|
|
95 |
height: 22px;\
|
|
96 |
margin: 0;\
|
|
97 |
padding: 0;\
|
|
98 |
position: relative;\
|
|
99 |
}\
|
|
100 |
.ace_searchbtn:last-child,\
|
|
101 |
.ace_replacebtn:last-child {\
|
|
102 |
border-top-right-radius: 3px;\
|
|
103 |
border-bottom-right-radius: 3px;\
|
|
104 |
}\
|
|
105 |
.ace_searchbtn:disabled {\
|
|
106 |
background: none;\
|
|
107 |
cursor: default;\
|
|
108 |
}\
|
|
109 |
.ace_searchbtn {\
|
|
110 |
background-position: 50% 50%;\
|
|
111 |
background-repeat: no-repeat;\
|
|
112 |
width: 27px;\
|
|
113 |
}\
|
|
114 |
.ace_searchbtn.prev {\
|
|
115 |
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADFJREFUeNpiSU1NZUAC/6E0I0yACYskCpsJiySKIiY0SUZk40FyTEgCjGgKwTRAgAEAQJUIPCE+qfkAAAAASUVORK5CYII=); \
|
|
116 |
}\
|
|
117 |
.ace_searchbtn.next {\
|
|
118 |
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADRJREFUeNpiTE1NZQCC/0DMyIAKwGJMUAYDEo3M/s+EpvM/mkKwCQxYjIeLMaELoLMBAgwAU7UJObTKsvAAAAAASUVORK5CYII=); \
|
|
119 |
}\
|
|
120 |
.ace_searchbtn_close {\
|
|
121 |
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAcCAYAAABRVo5BAAAAZ0lEQVR42u2SUQrAMAhDvazn8OjZBilCkYVVxiis8H4CT0VrAJb4WHT3C5xU2a2IQZXJjiQIRMdkEoJ5Q2yMqpfDIo+XY4k6h+YXOyKqTIj5REaxloNAd0xiKmAtsTHqW8sR2W5f7gCu5nWFUpVjZwAAAABJRU5ErkJggg==) no-repeat 50% 0;\
|
|
122 |
border-radius: 50%;\
|
|
123 |
border: 0 none;\
|
|
124 |
color: #656565;\
|
|
125 |
cursor: pointer;\
|
|
126 |
display: block;\
|
|
127 |
float: right;\
|
|
128 |
font-family: Arial;\
|
|
129 |
font-size: 16px;\
|
|
130 |
height: 14px;\
|
|
131 |
line-height: 16px;\
|
|
132 |
margin: 5px 1px 9px 5px;\
|
|
133 |
padding: 0;\
|
|
134 |
text-align: center;\
|
|
135 |
width: 14px;\
|
|
136 |
}\
|
|
137 |
.ace_searchbtn_close:hover {\
|
|
138 |
background-color: #656565;\
|
|
139 |
background-position: 50% 100%;\
|
|
140 |
color: white;\
|
|
141 |
}\
|
|
142 |
.ace_replacebtn.prev {\
|
|
143 |
width: 54px\
|
|
144 |
}\
|
|
145 |
.ace_replacebtn.next {\
|
|
146 |
width: 27px\
|
|
147 |
}"; |
|
148 |
var HashHandler = require("../keyboard/hash_handler").HashHandler; |
|
149 |
var keyUtil = require("../lib/keys"); |
|
150 |
||
151 |
dom.importCssString(searchboxCss, "ace_searchbox"); |
|
152 |
||
153 |
var html = '<div class="ace_search right">\ |
|
154 |
<button type="button" action="hide" class="ace_searchbtn_close"></button>\
|
|
155 |
<div class="ace_search_form">\
|
|
156 |
<input class="ace_search_field" placeholder="Search for" spellcheck="false"></input>\
|
|
157 |
<button type="button" action="findNext" class="ace_searchbtn next"></button>\
|
|
158 |
<button type="button" action="findPrev" class="ace_searchbtn prev"></button>\
|
|
159 |
</div>\
|
|
160 |
<div class="ace_replace_form">\
|
|
161 |
<input class="ace_search_field" placeholder="Replace with" spellcheck="false"></input>\
|
|
162 |
<button type="button" action="replace" class="ace_replacebtn">Replace</button>\
|
|
163 |
<button type="button" action="replaceAll" class="ace_replacebtn">All</button>\
|
|
164 |
</div>\
|
|
165 |
</div>'.replace(/>\s+/g, ">"); |
|
166 |
||
167 |
var SearchBox = function(editor, range, showReplaceForm) { |
|
168 |
var div = dom.createElement("div"); |
|
169 |
div.innerHTML = html; |
|
170 |
this.element = div.firstChild; |
|
171 |
||
172 |
this.$init(); |
|
173 |
this.setEditor(editor); |
|
174 |
};
|
|
175 |
||
176 |
(function() { |
|
177 |
this.setEditor = function(editor) { |
|
178 |
editor.searchBox = this; |
|
179 |
editor.container.appendChild(this.element); |
|
180 |
this.editor = editor; |
|
181 |
}; |
|
182 |
||
183 |
this.$init = function() { |
|
184 |
var sb = this.element; |
|
185 |
||
186 |
this.searchBox = sb.querySelector(".ace_search_form"); |
|
187 |
this.replaceBox = sb.querySelector(".ace_replace_form"); |
|
188 |
this.searchInput = this.searchBox.querySelector(".ace_search_field"); |
|
189 |
this.replaceInput = this.replaceBox.querySelector(".ace_search_field"); |
|
190 |
||
191 |
var _this = this; |
|
192 |
event.addListener(sb, "mousedown", function(e) { |
|
193 |
setTimeout(function(){ |
|
194 |
_this.activeInput.focus(); |
|
195 |
}, 0); |
|
196 |
event.stopPropagation(e); |
|
197 |
}); |
|
198 |
event.addListener(sb, "click", function(e) { |
|
199 |
var t = e.target; |
|
200 |
var action = t.getAttribute("action"); |
|
201 |
if (action && _this[action]) |
|
202 |
_this[action](); |
|
203 |
event.stopPropagation(e); |
|
204 |
}); |
|
205 |
||
206 |
event.addCommandKeyListener(sb, function(e, hashId, keyCode) { |
|
207 |
var keyString = keyUtil.keyCodeToString(keyCode); |
|
208 |
var command = _this.$searchBarKb.findKeyCommand(hashId, keyString); |
|
209 |
if (command && command.exec) { |
|
210 |
command.exec(_this); |
|
211 |
event.stopEvent(e); |
|
212 |
} |
|
213 |
}); |
|
214 |
||
215 |
this.$onChange = lang.delayedCall(function() { |
|
216 |
_this.find(false, false); |
|
217 |
}); |
|
218 |
||
219 |
event.addListener(this.searchInput, "input", function() { |
|
220 |
_this.$onChange.schedule(20); |
|
221 |
}); |
|
222 |
event.addListener(this.searchInput, "focus", function() { |
|
223 |
_this.activeInput = _this.searchInput; |
|
224 |
}); |
|
225 |
event.addListener(this.replaceInput, "focus", function() { |
|
226 |
_this.activeInput = _this.replaceInput; |
|
227 |
}); |
|
228 |
}; |
|
229 |
this.$closeSearchBarKb = new HashHandler([{ |
|
230 |
bindKey: "Esc", |
|
231 |
name: "closeSearchBar", |
|
232 |
exec: function(editor) { |
|
233 |
editor.searchBox.hide(); |
|
234 |
} |
|
235 |
}]); |
|
236 |
this.$searchBarKb = new HashHandler(); |
|
237 |
this.$searchBarKb.bindKeys({ |
|
238 |
"Ctrl-f|Command-f|Ctrl-H|Command-Option-F": function(sb) { |
|
239 |
var isReplace = sb.isReplace = !sb.isReplace; |
|
240 |
sb.replaceBox.style.display = isReplace ? "" : "none"; |
|
241 |
sb[isReplace ? "replaceInput" : "searchInput"].focus(); |
|
242 |
}, |
|
243 |
"esc": function(sb) { |
|
244 |
setTimeout(function() { sb.hide();}); |
|
245 |
}, |
|
246 |
"Return": function(sb) { |
|
247 |
if (sb.activeInput == sb.replaceInput) |
|
248 |
sb.replace(); |
|
249 |
sb.findNext(); |
|
250 |
}, |
|
251 |
"Shift-Return": function(sb) { |
|
252 |
if (sb.activeInput == sb.replaceInput) |
|
253 |
sb.replace(); |
|
254 |
sb.findPrev(); |
|
255 |
}, |
|
256 |
"Tab": function(sb) { |
|
257 |
(sb.activeInput == sb.replaceInput ? sb.searchInput : sb.replaceInput).focus(); |
|
258 |
} |
|
259 |
}); |
|
260 |
||
261 |
||
262 |
this.find = function(skipCurrent, backwards) { |
|
263 |
this.editor.find(this.searchInput.value, { |
|
264 |
skipCurrent: skipCurrent, |
|
265 |
backwards: backwards, |
|
266 |
wrap: true |
|
267 |
}); |
|
268 |
this.editor.session.highlight(this.editor.$search.$options.re); |
|
269 |
}; |
|
270 |
this.findNext = function() { |
|
271 |
this.find(true, false); |
|
272 |
}; |
|
273 |
this.findPrev = function() { |
|
274 |
this.find(true, true); |
|
275 |
}; |
|
276 |
this.replace = function() { |
|
277 |
this.editor.replace(this.replaceInput.value); |
|
278 |
this.findNext(); |
|
279 |
}; |
|
280 |
this.replaceAll = function() { |
|
281 |
this.editor.replaceAll(this.replaceInput.value); |
|
282 |
}; |
|
283 |
||
284 |
this.hide = function () { |
|
285 |
this.element.style.display = "none"; |
|
286 |
this.editor.keyBinding.removeKeyboardHandler(this.$closeSearchBarKb); |
|
287 |
this.editor.focus(); |
|
288 |
}; |
|
289 |
this.show = function(value, isReplace) { |
|
290 |
this.element.style.display = ""; |
|
291 |
this.replaceBox.style.display = isReplace ? "" : "none"; |
|
292 |
||
293 |
this.isReplace = isReplace; |
|
294 |
||
295 |
if (value) |
|
296 |
this.searchInput.value = value; |
|
297 |
this.searchInput.focus(); |
|
298 |
this.searchInput.select(); |
|
299 |
||
300 |
this.editor.keyBinding.addKeyboardHandler(this.$closeSearchBarKb); |
|
301 |
}; |
|
302 |
||
303 |
}).call(SearchBox.prototype); |
|
304 |
||
305 |
exports.SearchBox = SearchBox; |
|
306 |
||
307 |
exports.Search = function(editor, isReplace) { |
|
308 |
var sb = editor.searchBox || new SearchBox(editor); |
|
309 |
sb.show(editor.session.getTextRange(), isReplace); |
|
310 |
};
|
|
311 |
||
312 |
||
313 |
exports.ISearch = function(session, options) { |
|
314 |
this.$changeListener = this.$changeListener.bind(this); |
|
315 |
this.startRange = session.selection.toOrientedRange(); |
|
316 |
this.options = options || {}; |
|
317 |
};
|
|
318 |
||
319 |
(function(){ |
|
320 |
this.setSession = function(session) { |
|
321 |
if (this.session) { |
|
322 |
this.session.removeListener(this.$changeListener); |
|
323 |
} |
|
324 |
this.session = session; |
|
325 |
this.session.addListener(this.$changeListener); |
|
326 |
}; |
|
327 |
this.setSearchString = function() { |
|
328 |
||
329 |
}; |
|
330 |
this.getValue = function() { |
|
331 |
if (this.value == null) |
|
332 |
this.value = this.session.getValue(); |
|
333 |
return this.value; |
|
334 |
}; |
|
335 |
this.$changeListener = function() { |
|
336 |
this.value = null; |
|
337 |
}; |
|
338 |
this.find = function() { |
|
339 |
||
340 |
}; |
|
341 |
this.$edgeBefore = function() { |
|
342 |
this.cursor = this.startRange[this.options.backwards ? "start" : "end"]; |
|
343 |
}; |
|
344 |
this.$edgeAfter = function() { |
|
345 |
||
346 |
}; |
|
347 |
this.next = function(dir) { |
|
348 |
||
349 |
}; |
|
350 |
}).call(exports.ISearch.prototype); |
|
351 |
||
352 |
||
353 |
});
|