aboutsummaryrefslogtreecommitdiff
path: root/js/controllers/code-editor-controller.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/controllers/code-editor-controller.js')
-rw-r--r--js/controllers/code-editor-controller.js245
1 files changed, 245 insertions, 0 deletions
diff --git a/js/controllers/code-editor-controller.js b/js/controllers/code-editor-controller.js
new file mode 100644
index 00000000..f4ca6018
--- /dev/null
+++ b/js/controllers/code-editor-controller.js
@@ -0,0 +1,245 @@
1/* <copyright>
2This file contains proprietary software owned by Motorola Mobility, Inc.<br/>
3No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.<br/>
4(c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved.
5</copyright> */
6
7////////////////////////////////////////////////////////////////////////
8//
9var Montage = require("montage/core/core").Montage,
10 Component = require("montage/ui/component").Component;
11
12var CodeEditorController = exports.CodeEditorController = Montage.create(Component, {
13 hasTemplate: {
14 value: false
15 },
16
17 _codeEditor : {
18 value:null
19 },
20
21 codeEditor:{
22 get: function(){return this._codeEditor;},
23 set: function(value){this._codeEditor = value;}
24 },
25
26 codeCompletionSupport : {
27 value: {"javascript": true}
28 },
29
30 _automaticCodeComplete: {
31 value:false
32 },
33
34 automaticCodeComplete:{
35 get: function(){return this._automaticCodeComplete;},
36 set: function(value){this._automaticCodeComplete = value;}
37 },
38
39 _editorTheme: {
40 value:"default"
41 },
42
43 editorTheme:{
44 get: function(){return this._editorTheme;},
45 set: function(value){this._editorTheme = value;}
46 },
47
48 _zoomFactor:{
49 value:100
50 },
51
52 zoomFactor:{
53 get: function(){return this._zoomFactor;},
54 set: function(value){
55 this.handleZoom(value);
56 }
57 },
58
59 deserializedFromTemplate: {
60 value: function() {
61 //TODO:add logic to check some configuration file to load the right code editor
62 this.codeEditor = CodeMirror;
63 }
64 },
65
66 /**
67 * Public method
68 * Creates an editor instance
69 */
70 createEditor : {
71 value:function(doc, type){
72 var self = this, editorOptions = null;
73
74 editorOptions = {
75 lineNumbers: true,
76 matchBrackets:true,
77 mode: type,
78 onChange: function(){
79 var historySize = doc.editor.historySize();
80 if(historySize.undo>0){
81 doc.needsSave = true;
82 }else if(historySize.undo===0 && historySize.redo>0){
83 doc.needsSave = false;
84 }
85 },
86 onCursorActivity: function() {
87 doc.editor.matchHighlight("CodeMirror-matchhighlight");
88 doc.editor.setLineClass(doc.editor.hline, null, null);
89 doc.editor.hline = doc.editor.setLineClass(doc.editor.getCursor().line, null, "activeline");
90 }
91 };
92
93 //configure auto code completion if it is supported for that document type
94 if(this.codeCompletionSupport[type] === true){
95 editorOptions.onKeyEvent = function(cm, keyEvent){self._codeCompletionKeyEventHandler.call(self, cm, keyEvent, type)};
96 }
97
98 var editor = self.codeEditor.fromTextArea(doc.textArea, editorOptions);
99
100 //editor.setOption("theme", "night");
101
102 return editor;
103 }
104 },
105
106 /**
107 * Private method
108 * key event handler for showing code completion dropdown
109 */
110 _codeCompletionKeyEventHandler:{
111 enumerable:false,
112 value: function(cm, keyEvent, type) {
113 //===manually triggered code completion
114 if((this.automaticCodeComplete === false)){
115 if(keyEvent.ctrlKey && keyEvent.keyCode === 32){//Ctrl+Space
116 this.codeEditor.simpleHint(cm, this.codeEditor.javascriptHint);
117 }
118 }
119 //===automatic auto complete [performance is slower]
120 else if(this._showAutoComplete(type, keyEvent)){
121 this.codeEditor.simpleHint(cm, this.codeEditor.javascriptHint);
122 }
123 }
124 },
125
126 /**
127 * Private method
128 * checks for valid keyset to show code completion dropdown
129 */
130 _showAutoComplete : {
131 enumerable:false,
132 value:function(type, keyEvent){
133 var status=false;
134
135 switch(type){
136 case "javascript":
137 if((keyEvent.type === "keyup")//need seperate keycode set per mode
138 && ((keyEvent.keyCode > 47 && keyEvent.keyCode < 57)//numbers
139 || (keyEvent.keyCode > 64 && keyEvent.keyCode <91)//letters
140 || (keyEvent.keyCode === 190)//period
141 || (keyEvent.keyCode === 189)//underscore, dash
142 )
143 && !( (keyEvent.keyCode === 219)//open bracket [
144 || (keyEvent.ctrlKey || keyEvent.metaKey)//ctrl
145 || (keyEvent.keyCode === 221)//close bracket ]
146 || (keyEvent.shiftKey && keyEvent.keyCode === 219)//open bracket {
147 || (keyEvent.shiftKey && keyEvent.keyCode === 221)//close bracket }
148 || (keyEvent.shiftKey && keyEvent.keyCode === 57)//open bracket (
149 || (keyEvent.shiftKey && keyEvent.keyCode === 48)//close bracket )
150 || ((keyEvent.keyCode === 83) && (keyEvent.ctrlKey || keyEvent.metaKey))//ctrl+S
151 || ((keyEvent.keyCode === 90) && (keyEvent.ctrlKey || keyEvent.metaKey))//ctrl+z
152 || ((keyEvent.keyCode === 89) && (keyEvent.ctrlKey || keyEvent.metaKey))//ctrl+y
153 )
154 ){
155 status = true;
156 break;
157 }
158 default :
159 status = false;
160 }
161
162 return status;
163 }
164 },
165
166 handleCodeCompletionSupport:{
167 value:function(fileType){
168 var autoCodeCompleteElem = document.getElementsByClassName("autoCodeComplete")[0], elems=null, i=0;
169 if(autoCodeCompleteElem){
170 elems = autoCodeCompleteElem.getElementsByTagName("*");
171 }
172
173 if(elems && (this.codeCompletionSupport[fileType] === true)){
174 //enable elements
175 for(i=0;i<elems.length;i++){
176 if(elems[i].hasAttribute("disabled")){
177 elems[i].removeAttribute("disabled");
178 }
179 if(elems[i].classList.contains("disabled")){
180 elems[i].classList.remove("disabled");
181 }
182 }
183 }else if(elems && !this.codeCompletionSupport[fileType]){
184 //disable elements
185 for(i=0;i<elems.length;i++){
186 if(!elems[i].hasAttribute("disabled")){
187 elems[i].setAttribute("disabled", "disabled");
188 }
189 if(!elems[i].classList.contains("disabled")){
190 elems[i].classList.add("disabled");
191 }
192 }
193 }
194 }
195 },
196
197 getSelectedRange:{
198 value:function(editor){
199 return { from: editor.getCursor(true), to: editor.getCursor(false) };
200 }
201 },
202
203 autoFormatSelection:{
204 value: function(){
205 var range = this.getSelectedRange(this.application.ninja.documentController.activeDocument.editor);
206 this.application.ninja.documentController.activeDocument.editor.autoFormatRange(range.from, range.to);
207 }
208 },
209
210 commentSelection:{
211 value: function(isComment){
212 var range = this.getSelectedRange(this.application.ninja.documentController.activeDocument.editor);
213 this.application.ninja.documentController.activeDocument.editor.commentRange(isComment, range.from, range.to);
214 }
215 },
216
217 handleThemeSelection:{
218 value: function(){
219 this.application.ninja.documentController.activeDocument.editor.setOption("theme", this.editorTheme);
220 this.application.ninja.stage.stageView.applyTheme("cm-s-"+this.editorTheme);
221 }
222 },
223
224 handleZoom:{
225 value:function(value){
226