diff --git a/AppKit/NEWCPTableView.j b/AppKit/NEWCPTableView.j index 22e13a01f..32ef24b24 100644 --- a/AppKit/NEWCPTableView.j +++ b/AppKit/NEWCPTableView.j @@ -574,7 +574,9 @@ CPTableViewSelectionHighlightStyleSourceList = 1; // O(Columns) if table view contains hidden columns - (CPInteger)columnAtPoint:(CGPoint)aPoint { - if (!CGRectContainsPoint([self bounds], aPoint)) + var bounds = [self bounds]; + + if (!_CGRectContainsPoint(bounds, aPoint)) return CPNotFound; if (_dirtyTableColumnRangeIndex !== CPNotFound) @@ -895,7 +897,7 @@ CPTableViewSelectionHighlightStyleSourceList = 1; // remove? return; } - +console.profile("cell-load"); // SLOWMO /* var subviews = [self subviews], count = [subviews count]; @@ -923,6 +925,7 @@ CPTableViewSelectionHighlightStyleSourceList = 1; [self r:previouslyExposedRows c:newlyExposedColumns]; [self r:newlyExposedRows c:previouslyExposedColumns]; [self r:newlyExposedRows c:newlyExposedColumns]; +console.profileEnd("cell-load"); } - (void)r:(CPIndexSet)rows c:(CPIndexSet)columns diff --git a/Foundation/CPIndexSet.j b/Foundation/CPIndexSet.j index 50f7421a7..4b33b1995 100644 --- a/Foundation/CPIndexSet.j +++ b/Foundation/CPIndexSet.j @@ -35,7 +35,6 @@ @implementation CPIndexSet : CPObject { unsigned _count; - unsigned _cachedRangeIndex; CPArray _ranges; } @@ -75,7 +74,6 @@ { _count = 0; _ranges = []; - _cachedRangeIndex = 0; } return self; @@ -92,8 +90,7 @@ if (self) { _count = 1; - _ranges = [CPArray arrayWithObject:CPMakeRange(anIndex, 1)]; - _cachedRangeIndex = 0; + _ranges = [CPMakeRange(anIndex, 1)]; } return self; @@ -111,8 +108,7 @@ if (self) { _count = aRange.length; - _ranges = [CPArray arrayWithObject:aRange]; - _cachedRangeIndex = 0; + _ranges = [aRange]; } return self; @@ -131,13 +127,12 @@ { _count = [anIndexSet count]; _ranges = []; - _cachedRangeIndex = 0; - - var index = 0, - count = anIndexSet._ranges.length; - - for (; index < count; ++index) - _ranges.push(CPCopyRange(anIndexSet._ranges[index])); + + var otherRanges = anIndexSet._ranges, + otherRangesCount = otherRanges.length; + + while (otherRangesCount--) + _ranges[otherRangesCount] = CPCopyRange(otherRanges[otherRangesCount]); } return self; @@ -151,24 +146,26 @@ */ - (BOOL)isEqualToIndexSet:(CPIndexSet)anIndexSet { + if (!anIndexSet) + return NO; + // Comparisons to ourself are always return YES. - if (self == anIndexSet) + if (self === anIndexSet) return YES; - - var i = 0, - count = _ranges.length; + + var rangesCount = _ranges.length, otherRanges = anIndexSet._ranges; - + // If we have a discrepency in the number of ranges or the number of indexes, // simply return NO. - if (count != otherRanges.length || _count != [anIndexSet count]) - return NO; - - for (; i < count; ++i) - if (!CPEqualRanges(_ranges[i], otherRanges[i])) - return NO; - - return YES; + if (rangesCount !== otherRanges.length || _count !== anIndexSet._count) + return NO; + + while (count--) + if (!CPEqualRanges(_ranges[count], otherRanges[count])) + return NO; + + return YES; } /*! @@ -178,7 +175,7 @@ */ - (BOOL)containsIndex:(unsigned)anIndex { - return [self containsIndexesInRange:CPMakeRange(anIndex, 1)]; + return positionOfIndex(_ranges, anIndex) !== CPNotFound; } /*! @@ -187,29 +184,24 @@ */ - (BOOL)containsIndexesInRange:(CPRange)aRange { - if(!_count) + if (aRange.length <= 0) return NO; - var i = SOERangeIndex(self, aRange.location), - lower = aRange.location, - upper = CPMaxRange(aRange), - count = _ranges.length; + // If we have less total indexes than aRange, we can't possibly contain aRange. + if(_count < aRange.length) + return NO; - // Stop if the location is ever bigger than or equal to our - // non-inclusive upper bound - for(;i < count && _ranges[i].location < upper; ++i) - // The range must be a subset of one our ranges. - if (_ranges[i].location <= lower && CPMaxRange(_ranges[i]) >= upper) - { - _cachedRangeIndex = i; - return YES; - } - - // The value isn't here, but values greater than anIndex should - // start from here regardless. - _cachedRangeIndex = i; - - return NO; + // Search for first location + var rangeIndex = positionOfIndex(_ranges, aRange.location); + + // If we don't have the first location, then we don't contain aRange. + if (rangeIndex === CPNotFound) + return NO; + + var range = _ranges[rangeIndex]; + + // The intersection must contain all the indexes from the original range. + return CPIntersectionRange(range, aRange).length === aRange.length; } /*! @@ -218,22 +210,22 @@ */ - (BOOL)containsIndexes:(CPIndexSet)anIndexSet { - // Return YES if anIndexSet has no indexes - if(![anIndexSet count]) + var otherCount = anIndexSet._count; + + if(otherCount <= 0) return YES; - - // Return NO if we have no indexes. - if(!_count) + + // If we have less total indexes than anIndexSet, we can't possibly contain aRange. + if (_count < otherCount) return NO; - var i = 0, - count = _ranges.length; - - // This is fast thanks to the _cachedIndexRange. - for(; i < count; ++i) - if (![anIndexSet containsIndexesInRange:_ranges[i]]) + var otherRanges = anIndexSet._ranges, + otherRangesCount = otherRanges.length; + + while (otherRangesCount--) + if (![self containsIndexesInRange:otherRanges[otherRangesCount]]) return NO; - + return YES; } @@ -275,7 +267,10 @@ */ - (int)firstIndex { - return _count ? _ranges[0].location : CPNotFound; + if (_count > 0) + return _ranges[0].location; + + return CPNotFound; } /*! @@ -283,32 +278,41 @@ */ - (int)lastIndex { - return _count ? CPMaxRange(_ranges[_ranges.length - 1]) - 1 : CPNotFound; + if (_count > 0) + return CPMaxRange(_ranges[_ranges.length - 1]) - 1; + + return CPNotFound; } /*! Returns the first index value in the receiver which is greater than anIndex. @return the closest index or CPNotFound if no match was found */ -- (unsigned)indexGreaterThanIndex:(unsigned)anIndex +- (CPInteger)indexGreaterThanIndex:(CPInteger)anIndex { - if(!_count) - return CPNotFound; - - var i = SOERangeIndex(self, anIndex++), - count = _ranges.length; - - for(; i < count && anIndex >= CPMaxRange(_ranges[i]); ++i) ; + // The first possible index that would satisfy this requirement. + ++anIndex; - if (i == count) - return CPNotFound; - - _cachedRangeIndex = i; - - if (anIndex < _ranges[i].location) - return _ranges[i].location; + // Attempt to find it or something bigger. + var rangeIndex = assumedPositionOfIndex(_ranges, anIndex); - return anIndex; + // Nothing at all found? + if (rangeIndex === CPNotFound) + return CPNotFound; + + rangeIndex = CEIL(rangeIndex); + + if (rangeIndex >= _ranges.length) + return CPNotFound; + + var range = _ranges[rangeIndex]; + + // Check if it's actually in this range. + if (CPLocationInRange(anIndex, range)) + return anIndex; + + // If not, it must be the first element of this range. + return range.location; } /*! @@ -317,25 +321,29 @@ */ - (unsigned)indexLessThanIndex:(unsigned)anIndex { - if (!_count) - return CPNotFound; - - var i = GOERangeIndex(self, anIndex--); - - for (; i >= 0 && anIndex < _ranges[i].location; --i) ; + // The first possible index that would satisfy this requirement. + --anIndex; - if(i < 0) - return CPNotFound; - - _cachedRangeIndex = i; + // Attempt to find it or something smaller. + var rangeIndex = assumedPositionOfIndex(_ranges, anIndex); - if (CPLocationInRange(anIndex, _ranges[i])) + // Nothing at all found? + if (rangeIndex === CPNotFound) + return CPNotFound; + + rangeIndex = FLOOR(rangeIndex); + + if (rangeIndex < 0) + return CPNotFound; + + var range = _ranges[rangeIndex]; + + // Check if it's actually in this range. + if (CPLocationInRange(anIndex, range)) return anIndex; - - if (CPMaxRange(_ranges[i]) - 1 < anIndex) - return CPMaxRange(_ranges[i]) - 1; - return CPNotFound; + // If not, it must be the first element of this range. + return CPMaxRange(range) - 1; } /*! @@ -422,7 +430,7 @@ for (i = 0; i < _ranges.length; i++) { desc += _ranges[i].location; - if (_ranges[i].length > 1) desc += "-" + (CPMaxRange(_ranges[i])-1) + ":"+_ranges[i].length+":"; + if (_ranges[i].length > 1) desc += "-" + (CPMaxRange(_ranges[i])-1) + "["+_ranges[i].length+"]"; if (i+1 < _ranges.length) desc += " "; } desc += ")]"; @@ -452,13 +460,12 @@ */ - (void)addIndexes:(CPIndexSet)anIndexSet { - var i = 0, - ranges = anIndexSet._ranges, - count = ranges.length; - + var otherRanges = anIndexSet._ranges, + otherRangesCount = otherRanges.length; + // Simply add each range within anIndexSet. - for(; i < count; ++i) - [self addIndexesInRange:ranges[i]]; + while (otherRangesCount--) + [self addIndexesInRange:otherRanges[otherRangesCount]]; } /*! @@ -467,91 +474,52 @@ */ - (void)addIndexesInRange:(CPRange)aRange { - if (_ranges.length == 0) + // If empty range, bail. + if (aRange.length <= 0) + return; + + // If we currently don't have any indexes, this represents our entire set. + if (_count <= 0) { _count = aRange.length; + _ranges = [aRange]; - return [_ranges addObject:CPCopyRange(aRange)]; + return; + } +var x = aRange.location - 1, y = CPMaxRange(aRange); + var rangeCount = _ranges.length, + lhsRangeIndex = assumedPositionOfIndex(_ranges, aRange.location - 1), + lhsRangeIndexCEIL = CEIL(lhsRangeIndex); +try{ + if (lhsRangeIndexCEIL === lhsRangeIndex && lhsRangeIndexCEIL < rangeCount) + aRange = CPUnionRange(aRange, _ranges[lhsRangeIndexCEIL]); +}catch(e) { alert("123456789 " + lhsRangeIndexCEIL + " " + rangeCount + " " + lhsRangeIndex);} + var rhsRangeIndex = assumedPositionOfIndex(_ranges, CPMaxRange(aRange)), + rhsRangeIndexFLOOR = FLOOR(rhsRangeIndex); + + if (rhsRangeIndexFLOOR === rhsRangeIndex && rhsRangeIndexFLOOR > 0) + aRange = CPUnionRange(aRange, _ranges[rhsRangeIndexFLOOR]); +//print("the returned indxes were for searching for " + x + " to " + y + " are " + lhsRangeIndex + " and " + rhsRangeIndex); + var removalCount = rhsRangeIndexFLOOR - lhsRangeIndexCEIL + 1; + + if (removalCount === 1) + { + if (lhsRangeIndexCEIL < _ranges.length) + _count -= _ranges[lhsRangeIndexCEIL].length; + + _count += aRange.length; + _ranges[lhsRangeIndexCEIL] = aRange; } - - // FIXME: Should we really use SOERangeIndex here? There is no real - // reason the cached index would be a better guess than 0, and it - // would avoid a function call. - var i = SOERangeIndex(self, aRange.location), - count = _ranges.length, - padded = CPMakeRange(aRange.location - 1, aRange.length + 2), - maximum = CPMaxRange(aRange); - // If our range won't intersect with the last range, just append it to the end. - if (count && CPMaxRange(_ranges[count - 1]) < aRange.location) - [_ranges addObject:CPCopyRange(aRange)]; else - for (; i < count; ++i) - { - // This range is completely independent of existing ranges, - // simply add it to the array. - if (maximum < _ranges[i].location) - { - _count += aRange.length; - - // Keep _cachedRangeIndex relevant. - if (i < _cachedRangeIndex) ++_cachedRangeIndex; - - return [_ranges insertObject:CPCopyRange(aRange) atIndex:i]; - } - - if (CPIntersectionRange(_ranges[i], padded).length) - { - var union = CPUnionRange(_ranges[i], aRange); - - // We already contain all the indexes in this range. - if (union.length == _ranges[i].length) - return; - - // Pad the length to collapse with later ranges. - ++union.length; - - // We only need to check if we now intersect with any following - // ranges since if we now intersected with the previous range, - // it would have already been handled. We start at i and not i + 1 - // to make sure we subtract i's length. - var j = i; - - for(; j < count; ++j) - // Bail as soon as we don't find an intersection. - if(CPIntersectionRange(union, _ranges[j]).length) - _count -= _ranges[j].length; - else - break; - - // Remove the padding now that we are done. - // NOTE: We could have set _ranges[i] = CPCopyRange(union), - // and then not had to bother decerementing here, but this avoids - // a lookup above during unioning, and a function call (CPCopyRange). - --union.length; - _ranges[i] = union; - - // Now remove indexes [i + 1, j - 1] - if (j - i - 1 > 0) - { - var remove = CPMakeRange(i + 1, j - i - 1); - - _ranges[i] = CPUnionRange(_ranges[i], _ranges[j - 1]); - [_ranges removeObjectsInRange:remove]; - - // Keep _cachedRangeIndex relevant. - if (_cachedRangeIndex >= CPMaxRange(remove)) _cachedRangedIndex -= remove.length; - else if (CPLocationInRange(_cachedRangeIndex, remove)) _cachedRangeIndex = i; - } - - // Update count. - _count += _ranges[i].length; - - return; - } - } - - _count += aRange.length; + { + if (removalCount > 0) + [_ranges removeObjectsInRange:CPMakeRange(lhsRangeIndexCEIL, removalCount)]; + + [_ranges insertObject:aRange atIndex:lhsRangeIndexCEIL]; + + //FIXME COUNT! + } } // Removing Indexes @@ -571,13 +539,12 @@ */ - (void)removeIndexes:(CPIndexSet)anIndexSet { - var i = 0, - ranges = anIndexSet._ranges, - count = ranges.length; + var otherRanges = anIndexSet._ranges, + otherRangesCount = otherRanges.length; // Simply remove each index from anIndexSet - for(; i < count; ++i) - [self removeIndexesInRange:ranges[i]]; + while (otherRangesCount--) + [self removeIndexesInRange:otherRanges[otherRangesCount]]; } /*! @@ -587,7 +554,6 @@ { _ranges = []; _count = 0; - _cachedRangeIndex = 0; } /*! @@ -830,26 +796,72 @@ var CPIndexSetCountKey = @"CPIndexSetCountKey", @end -var SOERangeIndex = function(anIndexSet, anIndex) +var positionOfIndex = function(ranges, anIndex) { - var ranges = anIndexSet._ranges, - cachedRangeIndex = 0;//anIndexSet._cachedRangeIndex; - - if(cachedRangeIndex < ranges.length && anIndex >= ranges[cachedRangeIndex].location) - return cachedRangeIndex; + var low = 0, + high = ranges.length - 1; - return 0; + while (low <= high) + { + var middle = FLOOR(low + (high - low) / 2), + range = ranges[middle]; + + if (anIndex < range.location) + high = middle - 1; + + else if (anIndex >= CPMaxRange(range)) + low = middle + 1; + + else + return middle; + } + + return CPNotFound; } -var GOERangeIndex = function(anIndexSet, anIndex) +var assumedPositionOfIndex = function(ranges, anIndex) { - var ranges = anIndexSet._ranges, - cachedRangeIndex = anIndexSet._ranges.length;//anIndexSet._cachedRangeIndex; + var count = ranges.length; + + if (count <= 0) + return CPNotFound; + + var low = 0, + high = count * 2; + + while (low <= high) + { + var middle = FLOOR(low + (high - low) / 2), + position = middle / 2, + positionFLOOR = FLOOR(position); - if(cachedRangeIndex < ranges.length && anIndex <= ranges[cachedRangeIndex].location) - return cachedRangeIndex; - - return ranges.length - 1; + if (position === positionFLOOR) + {try{ + if (positionFLOOR - 1 >= 0 && anIndex < CPMaxRange(ranges[positionFLOOR - 1])) + high = middle - 1; + + else if (positionFLOOR < count && anIndex >= ranges[positionFLOOR].location) + low = middle + 1; + + else + return positionFLOOR - 0.5;}catch(e) { alert("here!");} + } + else + {try{ + var range = ranges[positionFLOOR]; + + if (anIndex < range.location) + high = middle - 1; + + else if (anIndex >= CPMaxRange(range)) + low = middle + 1; + + else + return positionFLOOR;}catch(e){alert("yes!");} + } + } + + return CPNotFound; } /*