/lenasys/trunk

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/lenasys/trunk

« back to all changes in this revision

Viewing changes to js/ace/ext-elastic_tabstops_lite.js

  • Committer: Henrik G.
  • Date: 2013-03-26 23:22:55 UTC
  • Revision ID: henrik.gustavsson@his.se-20130326232255-ik6snyatlbkf3zs1
First seed of Lenasys ... Needs to be Organized Further

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* ***** BEGIN LICENSE BLOCK *****
2
 
 * Distributed under the BSD license:
3
 
 *
4
 
 * Copyright (c) 2012, 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/elastic_tabstops_lite', ['require', 'exports', 'module' , 'ace/editor', 'ace/config'], function(require, exports, module) {
32
 
 
33
 
 
34
 
var ElasticTabstopsLite = function(editor) {
35
 
    this.$editor = editor;
36
 
    var self = this;
37
 
    var changedRows = [];
38
 
    var recordChanges = false;
39
 
    this.onAfterExec = function() {
40
 
        recordChanges = false;
41
 
        self.processRows(changedRows);
42
 
        changedRows = [];
43
 
    };
44
 
    this.onExec = function() {
45
 
        recordChanges = true;
46
 
    };
47
 
    this.onChange = function(e) {
48
 
        var range = e.data.range
49
 
        if (recordChanges) {
50
 
            if (changedRows.indexOf(range.start.row) == -1)
51
 
                changedRows.push(range.start.row);
52
 
            if (range.end.row != range.start.row)
53
 
                changedRows.push(range.end.row);
54
 
        }
55
 
    };
56
 
};
57
 
 
58
 
(function() {
59
 
    this.processRows = function(rows) {
60
 
        this.$inChange = true;
61
 
        var checkedRows = [];
62
 
 
63
 
        for (var r = 0, rowCount = rows.length; r < rowCount; r++) {
64
 
            var row = rows[r];
65
 
 
66
 
            if (checkedRows.indexOf(row) > -1)
67
 
                continue;
68
 
 
69
 
            var cellWidthObj = this.$findCellWidthsForBlock(row);
70
 
            var cellWidths = this.$setBlockCellWidthsToMax(cellWidthObj.cellWidths);
71
 
            var rowIndex = cellWidthObj.firstRow;
72
 
 
73
 
            for (var w = 0, l = cellWidths.length; w < l; w++) {
74
 
                var widths = cellWidths[w];
75
 
                checkedRows.push(rowIndex);
76
 
                this.$adjustRow(rowIndex, widths);
77
 
                rowIndex++;
78
 
            }
79
 
        }
80
 
        this.$inChange = false;
81
 
    };
82
 
 
83
 
    this.$findCellWidthsForBlock = function(row) {
84
 
        var cellWidths = [], widths;
85
 
        var rowIter = row;
86
 
        while (rowIter >= 0) {
87
 
            widths = this.$cellWidthsForRow(rowIter);
88
 
            if (widths.length == 0)
89
 
                break;
90
 
 
91
 
            cellWidths.unshift(widths);
92
 
            rowIter--;
93
 
        }
94
 
        var firstRow = rowIter + 1;
95
 
        rowIter = row;
96
 
        var numRows = this.$editor.session.getLength();
97
 
 
98
 
        while (rowIter < numRows - 1) {
99
 
            rowIter++;
100
 
 
101
 
            widths = this.$cellWidthsForRow(rowIter);
102
 
            if (widths.length == 0)
103
 
                break;
104
 
 
105
 
            cellWidths.push(widths);
106
 
        }
107
 
 
108
 
        return { cellWidths: cellWidths, firstRow: firstRow };
109
 
    };
110
 
 
111
 
    this.$cellWidthsForRow = function(row) {
112
 
        var selectionColumns = this.$selectionColumnsForRow(row);
113
 
 
114
 
        var tabs = [-1].concat(this.$tabsForRow(row));
115
 
        var widths = tabs.map(function (el) { return 0; } ).slice(1);
116
 
        var line = this.$editor.session.getLine(row);
117
 
 
118
 
        for (var i = 0, len = tabs.length - 1; i < len; i++) {
119
 
            var leftEdge = tabs[i]+1;
120
 
            var rightEdge = tabs[i+1];
121
 
 
122
 
            var rightmostSelection = this.$rightmostSelectionInCell(selectionColumns, rightEdge);
123
 
            var cell = line.substring(leftEdge, rightEdge);
124
 
            widths[i] = Math.max(cell.replace(/\s+$/g,'').length, rightmostSelection - leftEdge);
125
 
        }
126
 
        
127
 
        return widths;
128
 
    };
129
 
 
130
 
    this.$selectionColumnsForRow = function(row) {
131
 
        var selections = [], cursor = this.$editor.getCursorPosition();
132
 
        if (this.$editor.session.getSelection().isEmpty()) {
133
 
            if (row == cursor.row)
134
 
                selections.push(cursor.column);   
135
 
        }
136
 
 
137
 
        return selections;
138
 
    };
139
 
 
140
 
    this.$setBlockCellWidthsToMax = function(cellWidths) {
141
 
        var startingNewBlock = true, blockStartRow, blockEndRow, maxWidth;
142
 
        var columnInfo = this.$izip_longest(cellWidths);
143
 
 
144
 
        for (var c = 0, l = columnInfo.length; c < l; c++) {
145
 
            var column = columnInfo[c];
146
 
            if (!column.push) {
147
 
                console.error(column);
148
 
                continue;
149
 
            }
150
 
            column.push(NaN);
151
 
 
152
 
            for (var r = 0, s = column.length; r < s; r++) {
153
 
                var width = column[r];
154
 
                if (startingNewBlock) {
155
 
                    blockStartRow = r;
156
 
                    maxWidth = 0;
157
 
                    startingNewBlock = false;
158
 
                }
159
 
                if (isNaN(width)) {
160
 
                    blockEndRow = r;
161
 
 
162
 
                    for (var j = blockStartRow; j < blockEndRow; j++) {
163
 
                        cellWidths[j][c] = maxWidth;
164
 
                    }
165
 
                    startingNewBlock = true;
166
 
                }
167
 
 
168
 
                maxWidth = Math.max(maxWidth, width);
169
 
            }
170
 
        }
171
 
 
172
 
        return cellWidths;
173
 
    };
174
 
 
175
 
    this.$rightmostSelectionInCell = function(selectionColumns, cellRightEdge) {
176
 
        var rightmost = 0;
177
 
 
178
 
        if (selectionColumns.length) {
179
 
            var lengths = [];
180
 
            for (var s = 0, length = selectionColumns.length; s < length; s++) {
181
 
                if (selectionColumns[s] <= cellRightEdge)
182
 
                    lengths.push(s);
183
 
                else 
184
 
                    lengths.push(0);
185
 
            }
186
 
            rightmost = Math.max.apply(Math, lengths);
187
 
        }
188
 
 
189
 
        return rightmost;
190
 
    };
191
 
 
192
 
    this.$tabsForRow = function(row) {
193
 
        var rowTabs = [], line = this.$editor.session.getLine(row),
194
 
            re = /\t/g, match;
195
 
 
196
 
        while ((match = re.exec(line)) != null) {
197
 
            rowTabs.push(match.index);
198
 
        }
199
 
 
200
 
        return rowTabs;
201
 
    };
202
 
 
203
 
    this.$adjustRow = function(row, widths) {
204
 
        var rowTabs = this.$tabsForRow(row);
205
 
 
206
 
        if (rowTabs.length == 0)
207
 
            return;
208
 
        
209
 
        var bias = 0, location = -1;
210
 
        var expandedSet = this.$izip(widths, rowTabs);
211
 
 
212
 
        for (var i = 0, l = expandedSet.length; i < l; i++) {
213
 
            var w = expandedSet[i][0], it = expandedSet[i][1];
214
 
            location += 1 + w;
215
 
            it += bias;
216
 
            var difference = location - it;
217
 
 
218
 
            if (difference == 0)
219
 
                continue;
220
 
 
221
 
            var partialLine = this.$editor.session.getLine(row).substr(0, it );
222
 
            var strippedPartialLine = partialLine.replace(/\s*$/g, "");
223
 
            var ispaces = partialLine.length - strippedPartialLine.length;
224
 
 
225
 
            if (difference > 0) {
226
 
                this.$editor.session.getDocument().insertInLine({row: row, column: it + 1}, Array(difference + 1).join(" ") + "\t");
227
 
                this.$editor.session.getDocument().removeInLine(row, it, it + 1);
228
 
 
229
 
                bias += difference;
230
 
            }
231
 
 
232
 
            if (difference < 0 && ispaces >= -difference) {
233
 
                this.$editor.session.getDocument().removeInLine(row, it + difference, it);
234
 
                bias += difference;
235
 
            }
236
 
        }
237
 
    };
238
 
    this.$izip_longest = function(iterables) {
239
 
        if (!iterables[0])
240
 
            return [];
241
 
        var longest = iterables[0].length;
242
 
        var iterablesLength = iterables.length;
243
 
 
244
 
        for (var i = 1; i < iterablesLength; i++) {
245
 
            var iLength = iterables[i].length;
246
 
            if (iLength > longest)
247
 
                longest = iLength;
248
 
        }
249
 
        
250
 
        var expandedSet = [];
251
 
 
252
 
        for (var l = 0; l < longest; l++) {
253
 
            var set = [];
254
 
            for (var i = 0; i < iterablesLength; i++) {
255
 
                if (iterables[i][l] === "")
256
 
                    set.push(NaN);
257
 
                else
258
 
                    set.push(iterables[i][l]);
259
 
            }
260
 
 
261
 
            expandedSet.push(set);
262
 
        }
263
 
        
264
 
 
265
 
        return expandedSet;
266
 
    };
267
 
    this.$izip = function(widths, tabs) {
268
 
        var size = widths.length >= tabs.length ? tabs.length : widths.length;
269
 
        
270
 
        var expandedSet = [];
271
 
        for (var i = 0; i < size; i++) {
272
 
            var set = [ widths[i], tabs[i] ];
273
 
            expandedSet.push(set);
274
 
        }
275
 
        return expandedSet;
276
 
    };
277
 
 
278
 
}).call(ElasticTabstopsLite.prototype);
279
 
 
280
 
exports.ElasticTabstopsLite = ElasticTabstopsLite;
281
 
 
282
 
var Editor = require("../editor").Editor;
283
 
require("../config").defineOptions(Editor.prototype, "editor", {
284
 
    useElasticTabstops: {
285
 
        set: function(val) {
286
 
            if (val) {
287
 
                if (!this.elasticTabstops)
288
 
                    this.elasticTabstops = new ElasticTabstopsLite(this);
289
 
                this.commands.on("afterExec", this.elasticTabstops.onAfterExec);
290
 
                this.commands.on("exec", this.elasticTabstops.onExec);
291
 
                this.on("change", this.elasticTabstops.onChange);
292
 
            } else if (this.elasticTabstops) {
293
 
                this.commands.removeListener("afterExec", this.elasticTabstops.onAfterExec);
294
 
                this.commands.removeListener("exec", this.elasticTabstops.onExec);
295
 
                this.removeListener("change", this.elasticTabstops.onChange);
296
 
            }
297
 
        }
298
 
    }
299
 
});
300
 
 
301
 
});
 
 
b'\\ No newline at end of file'