sproutcore 0.9.6 → 0.9.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,590 +0,0 @@
1
- // ========================================================================
2
- // SproutCore
3
- // copyright 2006-2008 Sprout Systems, Inc.
4
- // ========================================================================
5
-
6
- require('Core') ;
7
- require('foundation/object') ;
8
-
9
- /**
10
- @class
11
-
12
- A sorted set stores objects in a sorted order based on a combination of
13
- sort keys.
14
-
15
- h2. Usage
16
-
17
- @extends SC.Object
18
- @extends SC.Array
19
- @since SproutCore 1.0
20
- */
21
- SC.SortedSet = SC.Object.extend(
22
- /** @scope SC.SortedSet.prototype */ {
23
-
24
- /**
25
- An array of property keys to use when sorting objects. This should be
26
- set when the set is created and not change during the lifetime of the
27
- object.
28
- */
29
- sortBy: [],
30
-
31
- compareObjects: function(v1, v2) {
32
- return (v1 < v2) ? -1 : (v1 > v2) ? 1 : 0 ;
33
- },
34
-
35
- init: function() {
36
- arguments.callee.base.call(this) ;
37
- this._root = null;
38
- this._cursor = null;
39
- this._ancestors = [];
40
- },
41
-
42
- /** _findNode */
43
- _findNode: function(value, saveAncestors) {
44
- if ( saveAncestors == null ) saveAncestors = false;
45
-
46
- var result = this._root;
47
-
48
- if ( saveAncestors ) {
49
- this._ancestors = [];
50
- }
51
-
52
- while ( result != null ) {
53
- var relation = this.compareObjects(value, result._value);
54
-
55
- if ( relation != 0 ) {
56
- if ( saveAncestors ) {
57
- this._ancestors.push(result);
58
- }
59
- if ( relation < 0 ) {
60
- result = result._left;
61
- } else {
62
- result = result._right;
63
- }
64
- } else {
65
- break;
66
- }
67
- }
68
-
69
- return result;
70
- },
71
-
72
- /** _maxNode */
73
- _maxNode: function(node, saveAncestors) {
74
- if ( node == null ) node = this._root;
75
- if ( saveAncestors == null ) saveAncestors = false;
76
-
77
- if ( node != null ) {
78
- while ( node._right != null ) {
79
- if ( saveAncestors ) {
80
- this._ancestors.push(node);
81
- }
82
- node = node._right;
83
- }
84
- }
85
-
86
- return node;
87
- },
88
-
89
- /** _minNode */
90
- _minNode: function(node, saveAncestors) {
91
- if ( node == null ) node = this._root;
92
- if ( saveAncestors == null ) saveAncestors = false;
93
-
94
- if ( node != null ) {
95
- while ( node._left != null ) {
96
- if ( saveAncestors ) {
97
- this._ancestors.push(node);
98
- }
99
- node = node._left;
100
- }
101
- }
102
-
103
- return node;
104
- },
105
-
106
- /** _nextNode */
107
- _nextNode: function(node) {
108
- if ( node != null ) {
109
- if ( node._right != null ) {
110
- this._ancestors.push(node);
111
- node = this._minNode(node._right, true);
112
- } else {
113
- var ancestors = this._ancestors;
114
- parent = ancestors.pop();
115
-
116
- while ( parent != null && parent._right === node ) {
117
- node = parent;
118
- parent = ancestors.pop();
119
- }
120
-
121
- node = parent;
122
- }
123
- } else {
124
- this._ancestors = [];
125
- node = this._minNode(this._root, true);
126
- }
127
-
128
- return node;
129
- },
130
-
131
- /** _previousNode */
132
- _previousNode: function(node) {
133
- if ( node != null ) {
134
- if ( node._left != null ) {
135
- this._ancestors.push(node);
136
- node = this._maxNode(node._left, true);
137
- } else {
138
- var ancestors = this._ancestors;
139
- parent = ancestors.pop();
140
-
141
- while ( parent != null && parent._left === node ) {
142
- node = parent;
143
- parent = ancestors.pop();
144
- }
145
-
146
- node = parent;
147
- }
148
- } else {
149
- this._ancestors = [];
150
- node = this._maxNode(this._root, true);
151
- }
152
-
153
- return node;
154
- },
155
-
156
- /**
157
- Adds a new object to the tree. The object must respond to the
158
- compareMethod.
159
- */
160
- add: function(value) {
161
- var result;
162
-
163
- if ( this._root == null ) {
164
- result = this._root = new SC.RedBlackNode(value, this);
165
- } else {
166
- var addResult = this._root.add(value);
167
-
168
- this._root = addResult[0];
169
- result = addResult[1];
170
- }
171
-
172
- return result;
173
- },
174
-
175
-
176
- find: function(value) {
177
- var node = this._findNode(value);
178
-
179
- return ( node != null ) ? node._value : null;
180
- },
181
-
182
- findNext: function(value) {
183
- var current = this._findNode(value, true);
184
-
185
- current = this._nextNode(current);
186
-
187
- return (current != null ) ? current._value : null;
188
- },
189
-
190
- findPrevious: function(value) {
191
- var current = this._findNode(value, true);
192
-
193
- current = this._previousNode(current);
194
-
195
- return (current != null ) ? current._value : null;
196
- },
197
-
198
- max: function() {
199
- var result = this._maxNode();
200
-
201
- return ( result != null ) ? result._value : null;
202
- },
203
-
204
- min: function() {
205
- var result = this._minNode();
206
-
207
- return ( result != null ) ? result._value : null;
208
- },
209
-
210
- next: function() {
211
- this._cursor = this._nextNode(this._cursor);
212
-
213
- return ( this._cursor ) ? this._cursor._value : null;
214
- },
215
-
216
- previous: function() {
217
- this._cursor = this._previousNode(this._cursor);
218
-
219
- return ( this._cursor ) ? this._cursor._value : null;
220
- },
221
-
222
- remove: function(value) {
223
- var result;
224
-
225
- if ( this._root != null ) {
226
- var remResult = this._root.remove(value);
227
-
228
- this._root = remResult[0];
229
- result = remResult[1];
230
- } else {
231
- result = null;
232
- }
233
-
234
- return result;
235
- },
236
-
237
- traverse: function(func) {
238
- if ( this._root != null ) {
239
- this._root.traverse(func);
240
- }
241
- },
242
-
243
- toString: function() {
244
- var lines = [];
245
-
246
- if ( this._root != null ) {
247
- var indentText = " ";
248
- var stack = [[this._root, 0, "^"]];
249
-
250
- while ( stack.length > 0 ) {
251
- var current = stack.pop();
252
- var node = current[0];
253
- var indent = current[1];
254
- var line = "";
255
-
256
- for ( var i = 0; i < indent; i++ ) {
257
- line += indentText;
258
- }
259
-
260
- line += current[2] + "(" + node.toString() + ")";
261
- lines.push(line);
262
-
263
- if ( node._right != null ) stack.push([node._right, indent+1, "R"]);
264
- if ( node._left != null ) stack.push([node._left, indent+1, "L"]);
265
- }
266
- }
267
-
268
- return lines.join("\n");
269
- }
270
-
271
- });
272
-
273
- /*****
274
- *
275
- * SC.RedBlackNode.js
276
- *
277
- * copyright 2004, Kevin Lindsey
278
- * licensing info available at: http://www.kevlindev.com/license.txt
279
- *
280
- *****/
281
-
282
- /*****
283
- *
284
- * constructor
285
- *
286
- *****/
287
- SC.RedBlackNode = function(value, owner) {
288
- this._owner = owner ;
289
- this._left = null;
290
- this._right = null;
291
- this._value = value;
292
- this._height = 1;
293
- this._count = 1 ;
294
- } ;
295
-
296
- SC.RedBlackNode.prototype.count = function() {
297
- if (!this._count) {
298
- this._count = 1 ;
299
- this._count += (this._left) ? this._left.count() : 0 ;
300
- this._count += (this._right) ? this._right.count() : 0;
301
- }
302
- return this._count ;
303
- };
304
-
305
- /**
306
- Returns the node at the specified index. Uses counts.
307
-
308
- Remember: left branch is before the right branch.
309
- */
310
- SC.RedBlackNode.prototype.nodeAt = function(idx) {
311
- var leftCount = (this._left) ? this._left.count() : 0 ;
312
- if (idx === leftCount) return this; // its me!
313
-
314
- // look lower
315
- if (idx < leftCount) {
316
- return (this._left) ? this._left.nodeAt(idx) : null ;
317
-
318
- // look higher
319
- } else {
320
- return (this._right) ? this._right.nodeAt(idx - leftCount) : null;
321
- }
322
- };
323
-
324
- /*****
325
- *
326
- * add
327
- *
328
- *****/
329
- SC.RedBlackNode.prototype.add = function(value) {
330
- var relation = this._owner.compareObjects(value, this._value);
331
- var addResult;
332
- var result;
333
- var newNode;
334
-
335
- if ( relation != 0 ) {
336
- if ( relation < 0 ) {
337
- if ( this._left != null ) {
338
- addResult = this._left.add(value);
339
- this._left = addResult[0];
340
- newNode = addResult[1];
341
- } else {
342
- newNode = this._left = new SC.RedBlackNode(value, this._owner);
343
- }
344
- } else if ( relation > 0 ) {
345
- if ( this._right != null ) {
346
- addResult = this._right.add(value);
347
- this._right = addResult[0];
348
- newNode = addResult[1];
349
- } else {
350
- newNode = this._right = new SC.RedBlackNode(value, this._owner);
351
- }
352
- }
353
- result = [this.balanceTree(), newNode];
354
- } else {
355
- result = [this, this];
356
- }
357
-
358
- // add to the return
359
- if (result[0]._count != null) result[0]._count = null ;
360
- return result;
361
- };
362
-
363
-
364
- /*****
365
- *
366
- * balanceTree
367
- *
368
- *****/
369
- SC.RedBlackNode.prototype.balanceTree = function() {
370
- var leftHeight = (this._left != null) ? this._left._height : 0;
371
- var rightHeight = (this._right != null) ? this._right._height : 0;
372
- var result;
373
-
374
- if ( leftHeight > rightHeight + 1 ) {
375
- result = this.swingRight();
376
- } else if ( rightHeight > leftHeight + 1 ) {
377
- result = this.swingLeft();
378
- } else {
379
- this.setHeight();
380
- result = this;
381
- }
382
-
383
- return result;
384
- };
385
-
386
-
387
- /*****
388
- *
389
- * join
390
- *
391
- *****/
392
- SC.RedBlackNode.prototype.join = function(that) {
393
- var result;
394
-
395
- if ( that == null ) {
396
- result = this;
397
- } else {
398
- var top;
399
-
400
- if ( this._height > that._height ) {
401
- top = this;
402
- top._right = that.join(top._right);
403
- } else {
404
- top = that;
405
- top._left = this.join(top._left);
406
- }
407
-
408
- result = top.balanceTree();
409
- }
410
-
411
- return result;
412
- };
413
-
414
-
415
- /*****
416
- *
417
- * moveLeft
418
- *
419
- *****/
420
- SC.RedBlackNode.prototype.moveLeft = function() {
421
- var right = this._right;
422
- var rightLeft = right._left;
423
-
424
- this._right = rightLeft;
425
- right._left = this;
426
- this.setHeight();
427
- right.setHeight();
428
-
429
- return right;
430
- };
431
-
432
-
433
- /*****
434
- *
435
- * moveRight
436
- *
437
- *****/
438
- SC.RedBlackNode.prototype.moveRight = function() {
439
- var left = this._left;
440
- var leftRight = left._right;
441
-
442
- this._left = leftRight;
443
- left._right = this;
444
- this.setHeight();
445
- left.setHeight();
446
-
447
- return left;
448
- };
449
-
450
-
451
- /*****
452
- *
453
- * remove
454
- *
455
- *****/
456
- SC.RedBlackNode.prototype.remove = function(value) {
457
- var relation = this._owner.compareObjects(value, this._value);
458
- var remResult;
459
- var result;
460
- var remNode;
461
-
462
- if ( relation != 0 ) {
463
- if ( relation < 0 ) {
464
- if ( this._left != null ) {
465
- remResult = this._left.remove(value);
466
- this._left = remResult[0];
467
- remNode = remResult[1];
468
- } else {
469
- remNode = null;
470
- }
471
- } else {
472
- if ( this._right != null ) {
473
- remResult = this._right.remove(value);
474
- this._right = remResult[0];
475
- remNode = remResult[1];
476
- } else {
477
- remNode = null;
478
- }
479
- }
480
-
481
- result = this;
482
- } else {
483
- remNode = this;
484
-
485
- if ( this._left == null ) {
486
- result = this._right;
487
- } else if ( this._right == null ) {
488
- result = this._left;
489
- } else {
490
- result = this._left.join(this._right);
491
- this._left = null;
492
- this._right = null;
493
- }
494
- }
495
-
496
- if ( remNode != null ) {
497
- if ( result != null ) {
498
- result = [result.balanceTree(), remNode];
499
- } else {
500
- result = [result, remNode];
501
- }
502
- } else {
503
- result = [this, null];
504
- }
505
-
506
- if (result[0]._count != null) result[0]._count = null ;
507
- return result ;
508
- };
509
-
510
-
511
- /*****
512
- *
513
- * setHeight
514
- *
515
- *****/
516
- SC.RedBlackNode.prototype.setHeight = function() {
517
- var leftHeight = (this._left != null) ? this._left._height : 0;
518
- var rightHeight = (this._right != null) ? this._right._height : 0;
519
-
520
- this._height = (leftHeight < rightHeight) ? rightHeight + 1 : leftHeight + 1;
521
- };
522
-
523
-
524
- /*****
525
- *
526
- * swingLeft
527
- *
528
- *****/
529
- SC.RedBlackNode.prototype.swingLeft = function() {
530
- var right = this._right;
531
- var rightLeft = right._left;
532
- var rightRight = right._right;
533
- var left = this._left;
534
-
535
- var leftHeight = (left != null ) ? left._height : 0;
536
- var rightLeftHeight = (rightLeft != null ) ? rightLeft._height : 0;
537
- var rightRightHeight = (rightRight != null ) ? rightRight._height : 0;
538
-
539
- if ( rightLeftHeight > rightRightHeight ) {
540
- this._right = right.moveRight();
541
- }
542
-
543
- return this.moveLeft();
544
- };
545
-
546
-
547
- /*****
548
- *
549
- * swingRight
550
- *
551
- *****/
552
- SC.RedBlackNode.prototype.swingRight = function() {
553
- var left = this._left;
554
- var leftRight = left._right;
555
- var leftLeft = left._left;
556
- var right = this._right;
557
-
558
- var rightHeight = (right != null ) ? right._height : 0;
559
- var leftRightHeight = (leftRight != null ) ? leftRight._height : 0;
560
- var leftLeftHeight = (leftLeft != null ) ? leftLeft._height : 0;
561
-
562
- if ( leftRightHeight > leftLeftHeight ) {
563
- this._left = left.moveLeft();
564
- }
565
-
566
- return this.moveRight();
567
- };
568
-
569
-
570
- /*****
571
- *
572
- * traverse
573
- *
574
- *****/
575
- SC.RedBlackNode.prototype.traverse = function(func) {
576
- if ( this._left != null ) this._left.traverse(func);
577
- func(this);
578
- if ( this._right != null ) this._right.traverse(func);
579
- };
580
-
581
-
582
- /*****
583
- *
584
- * toString
585
- *
586
- *****/
587
- SC.RedBlackNode.prototype.toString = function() {
588
- return this._value.toString();
589
- };
590
-