sproutcore 0.9.6 → 0.9.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
-